Python: iterate through dictionary and create list with results - python

I would like to iterate through a dictionary in Python in the form of:
dictionary = {
'company': {
0: 'apple',
1: 'berry',
2: 'pear'
},
'country': {
0:'GB',
1:'US',
2:'US'
}
}
To grab for example:
every [company, country] if country is "US"
So I get a list in the form:
[["berry", "US"], ["pear", "US"]]

I suppose your keys are strings as well and the output is a list of lists, where the elements are strings, too. Then this problem can be solved via list comprehension.
The idea is to use list comprehension to fill the list of [company, country]-lists, but only if the country is 'US'. key represents the keys of the inner dictionaries (i.e 0, 1, 2).
dictionary = {'company': {0: 'apple', 1: 'berry', 2: 'pear'}, 'country': {0: 'GB', 1: 'US', 2:'US'}}
y = [[dictionary['company'][key], dictionary['country'][key]] for key in dictionary['country'] if dictionary['country'][key] == 'US']
It returns
[['berry', 'US'], ['pear', 'US']]

myList = []
list(map(lambda x: myList.append(x) if x[1]=='US' else None,
zip(dictionary['company'].values(), dictionary['country'].values())))

Related

Create many lists from list of dictionaries that have different structures

I have a big list of dictionaries. And the dictionaries don´t have the same structure. But, I don´t know all the structures (my list has 1 million elements).
For example:
mylist = [{'name': 'Juan Carlos','age':38},{'name':'David','country':'Brazil'},
{'name':'Agustina', 'country': 'Argentina'},{'name': 'Renzo','age':24}]
I want to separate mylist into different lists, and each list has dictionaries with the same keys.
For example:
list1 = [{'name': 'Juan Carlos','age':38},{'name': 'Renzo','age':24}]
list2 = [{'name':'David','country':'Brazil'},{'name':'Agustina', 'country': 'Argentina'}]
The problem is I don´t know how many sublists I'm going to have.
To do this, you need to create a dictionary where the key is the set of keys that are present:
mylist = [{'name': 'Juan Carlos','age':38},{'name':'David','country':'Brazil'},{'name':'Agustina', 'country': 'Argentina'},{'name': 'Renzo','age':24}]
sublists = {}
for sl in mylist:
keys = tuple(set(sl.keys()))
if keys not in sublists:
sublists[keys] = []
sublists[keys].append( sl )
print( sublists )
Output:
{('name', 'age'): [{'name': 'Juan Carlos', 'age': 38}, {'name': 'Renzo', 'age': 24}], ('name', 'country'): [{'name': 'David', 'country': 'Brazil'}, {'name': 'Agustina', 'country': 'Argentina'}]}
You can use a frozenset of keys as a new key:
mylist = [{'name': 'Juan Carlos','age':38},{'name':'David','country':'Brazil'},
{'name':'Agustina', 'country': 'Argentina'},{'name': 'Renzo','age':24}]
sep = {}
for d in mylist:
sep.setdefault(frozenset(d), []).append(d)
and then you can get a list of lists:
print(sep.values())

python, map name from a list to a list of dict

I have the following list and list of dicts:
data = [dict(position=1, value=150.3),
dict(position=0, value=28.5),
dict(position=2, value=1050.3)]
names = ["CL", "ES", "EUR"]
I would like to map the values of the list into the list of dicts so they match the value stated in the key "position" of the dict - to get the following result:
data = [dict(name="ES", position=1, value=150.3),
dict(name="CL", position=0, value=28.5),
dict(name="EUR", position=2, value=1050.3)]
Is there any "smart" and pythonic way to achieve that?
First of all, please present your question in actual Python form. dict is a type; the way you represent dictionaries in Python is with {}.
Also, you don't have "a dict and list", you have two lists, one of which consists of three dictionaries. So:
data = [
{'position': 1, 'value': 150.3},
{'position': 0, 'value': 28.5},
{'position': 2, 'value': 1050.3}
]
names = ["CL", "ES", "EUR"]
So, given that you do have lists, there is no concern about ordering. A simple loop will give you what you want:
for d in data:
d['name'] = names[d['position']]
This updates data in place:
>>> data
[{'position': 1, 'name': 'ES', 'value': 150.3}, {'position': 0, 'name': 'CL', 'value': 28.5}, {'position': 2, 'name': 'EUR', 'value': 1050.3}]
You can use a list comprehension and dictionary update:
data = [dict(position = 2, value=150.3),
dict(position = 1, value = 28.5),
dict(position=3, value=1050.3)]
names = ['CL', 'ES', 'EUR']
# Sort names according to "position" value of the dictionary
sorted_names = [names[idx] for idx in map(lambda x: x['position'], data)]
# Update modifies inplace
_ = [data[idx].update({'name' : el}) for idx, el in enumerate(sorted_names)]
Which gives the expected output:
data
[{'name': 'ES', 'position': 2, 'value': 150.3},
{'name': 'CL', 'position': 1, 'value': 28.5},
{'name': 'EUR', 'position': 3, 'value': 1050.3}]
You could try:
data = [{"position": 2, "value": 150},
{"position": 1, "value": 200}]
names = ["CL", "ES"]
for item in data:
item["name"] = names[item["pos"] - 1]
Where we go through all the dictionaries in the list, then for each dictionary we set the "name" key to be equal to the value in data at the position described in item["pos"] minus 1.
This of course assumes your data is clean and all items in data correctly map to items in names.
If this is not the case, use a try-except:
for item in data:
try:
item["name"] = names[item["pos"] - 1]
except IndexError:
item["name"] = None
You can also use the update method on the dictionary elements in the list, if you like the keyword-argument convention, as the style of your question suggests.
for item in data:
item.update(name=names[item["position"]])
A one liner implementation using list comprehension.
print [dict(d.items()+[('name',names[d['position']-1])]) for d in data]

Remove dictionary from list with multiple conditions

list1 = [
{'id': 1, 'country': 'Italy'},
{'id': 2, 'country': 'Spain'},
{'id': 3, 'country': 'Japan'}
]
I use this code to remove from list1 every dictionary that has country != Italy:
list2 = [element for element in list1 if element['country'] == 'Italy']
But I to include in list2 dictionaries which country == 'Italy' AND country == 'Spain' and remove all the others (or even better pop them from list1 without creating another one). How can I do this in one line=
If you really want a one-liner, you can use a list comprehension with an in-place list update:
list1[:] = [d for d in list1 if d['country'] in ('Spain', 'Italy')]

Split python list in filtered list of multiple list and store them in single list

I have an exhaustive list of different categories with me:
myList = [
{'name': 'Sasha', 'category': 'Dog'},
{'name': 'Meow', 'category': 'Cat'},
{'name': 'Bark', 'category': 'Dog'}
]
I want them to break and a create smaller list within this bigList. It would be similar to this:
bigList = [
[
{'category': 'Dog', 'name': 'Sasha'},
{'category': 'Dog', 'name': 'Bark'}
],
[
{'category': 'Cat', 'name': 'Meow'}
]
]
Here is the python logic for iterating the loop:
bigList = []
prev = ''
for s in myList:
newList = []
if s['category'] != prev:
for m in myList:
if m['category'] == s['category']:
newList.append(m)
bigList.append(newList)
prev = s['category']
This has done the trick for me but I would like to know how can I optimize the above logic in for loop for more shorter and efficient code.
You can do this in two steps with groupby as commented by #roganjosh:
from itertools import groupby
# step 1: sort the list by category, we need this step because groupby only groups same
# adjacent values so we need to sort the list so that same category are close to each other
sort_list = sorted(myList, key = lambda x: x["category"])
# step 2: group by the category and create a new sub list for each group
[list(g) for _, g in groupby(sort_list, key = lambda x: x['category'])]
#[[{'category': 'Cat', 'name': 'Meow'}],
# [{'category': 'Dog', 'name': 'Sasha'}, {'category': 'Dog', 'name': 'Bark'}]]
Sorting can be expensive for large lists.
Starting with your data:
my_list = [
{'name': 'Sasha', 'category': 'Dog'},
{'name': 'Meow', 'category': 'Cat'},
{'name': 'Bark', 'category': 'Dog'}
]
This loops through all elements of your list once and rembers what its has already seen before in a dictionary:
res = []
seen = {}
for entry in my_list:
val = seen.setdefault(entry['category'], [])
if not val:
res.append(val)
val.append(entry)
It appends a new list only for not yet seen entries to res but all entries to the corresponding nested list val that it got from the seen dictionary. So, the same val is in res and in seen. Hence, appending to val will enlarge val and the effect can be seen no matter if your access val through res and or seen. The line val = seen.setdefault(entry['category'], []) gives you either an existing list, if the category was seen before or, a new empty list if the category was encountered the first time. At the same time, if the category is not yet in seen, it adds a new key with an empty list as value to seen.
This is the result:
import pprint
pprint.pprint(res)
[[{'category': 'Dog', 'name': 'Sasha'}, {'category': 'Dog', 'name': 'Bark'}],
[{'category': 'Cat', 'name': 'Meow'}]]

generate list from values of certain field in list of objects

How would I generate a list of values of a certain field of objects in a list?
Given the list of objects:
[ {name: "Joe", group: 1}, {name: "Kirk", group: 2}, {name: "Bob", group: 1}]
I want to generate list of the name field values:
["Joe", "Kirk", "Bob"]
The built-in filter() function seems to come close, but it will return the entire objects themselves.
I'd like a clean, one line solution such as:
filterLikeFunc(function(obj){return obj.name}, mylist)
Sorry, I know that's c syntax.
Just replace filter built-in function with map built-in function.
And use get function which will not give you key error in the absence of that particular key to get value for name key.
data = [{'name': "Joe", 'group': 1}, {'name': "Kirk", 'group': 2}, {'name': "Bob", 'group': 1}]
print map(lambda x: x.get('name'), data)
In Python 3.x
print(list(map(lambda x: x.get('name'), data)))
Results:
['Joe', 'Kirk', 'Bob']
Using List Comprehension:
print [each.get('name') for each in data]
Using a list comprehension approach you get:
objects = [{'group': 1, 'name': 'Joe'}, {'group': 2, 'name': 'Kirk'}, {'group': 1, 'name': 'Bob'}]
names = [i["name"] for i in objects]
For a good intro to list comprehensions, see https://docs.python.org/2/tutorial/datastructures.html
Just iterate over your list of dicts and pick out the name value and put them in a list.
x = [ {'name': "Joe", 'group': 1}, {'name': "Kirk", 'group': 2}, {'name': "Bob", 'group': 1}]
y = [y['name'] for y in x]
print(y)

Categories