Related to my previous post, would it be possible to separate the list of weirdly combined animals and their attribute (denoted in #)?
Dataset:
the_list = pd.Series([["dog", "cat", "#paws"],["gorilla"],["goat", "#beard","#hoofs"],["goldfish", "#fins", "#bigeyes", "#scales"]])
My Code:
category1 = []
category2 = []
for word_list in the_list:
category1.append([{v : 1} for v in word_list if not "#" in v])
category2.append([{v : 1} for v in word_list if "#" in v])
Here's the result:
Category 1:
[{'dog': 1}, {'cat': 1}, {'gorilla': 1}, {'goat': 1}, {'goldfish': 1}]
Category 2:
[[{'#paws': 1}],
[],
[{'#beard': 1}, {'#hoofs': 1}],
[{'#fins': 1}, {'#bigeyes': 1}, {'#scales': 1}]]
But what I need is to join all the elements of the same index instead of creating a separate dictionary for them
Category1:
[{'dog': 1, 'cat': 1},
{'gorilla': 1},
{'goat': 1},
{'goldfish': 1}]
Category2:
[{'#paws': 1}, # from dog, cat
{'No Category 2': 1}, #from gorilla
{"#beard" : 1,"#hoofs" : 1}, #from goat
{'#fins': 1, '#bigeyes': 1, '#scales': 1}] #from goldfish
Use dict.fromkeys:
category1 = []
category2 = []
for word_list in the_list:
category1.append(dict.fromkeys([v for v in word_list if not '#' in v] or ['No Category 1'], 1))
category2.append(dict.fromkeys([v for v in word_list if '#' in v] or ['No Category 2'], 1))
Output:
#category1
[{'cat': 1, 'dog': 1}, {'gorilla': 1}, {'goat': 1}, {'goldfish': 1}]
#category2
[{'#paws': 1},
{'No Category 2': 1},
{'#beard': 1, '#hoofs': 1},
{'#bigeyes': 1, '#fins': 1, '#scales': 1}]
Use dict
Ex:
category1 = []
category2 = []
the_list = pd.Series([["dog", "cat", "#paws"],["gorilla"],["goat", "#beard","#hoofs"],["goldfish", "#fins", "#bigeyes", "#scales"]])
for word_list in the_list:
category1.append(dict((v , 1) for v in word_list if not "#" in v))
category2.append(dict((v , 1) for v in word_list if "#" in v) or {'No Category 2': 1})
Output:
[{'cat': 1, 'dog': 1}, {'gorilla': 1}, {'goat': 1}, {'goldfish': 1}]
[{'#paws': 1},
{'No Category 2': 1},
{'#beard': 1, '#hoofs': 1},
{'#bigeyes': 1, '#fins': 1, '#scales': 1}]
Related
Was wondering if anyone could help me with counting duplicate dictionarys. I have this list:
a = [{'key1':1, 'key2':2, 'key3':3, 'count': 0},
{'key1':1, 'key2':2, 'key3':4, 'count': 0},
{'key1':3, 'key2':2, 'key3':4, 'count': 0},
{'key1':1, 'key2':2, 'key3':3, 'count': 0}]
i`m lookig to count all duplicates and once it is match remove copy and append to that dictionry ['count'] += 1. so final result might look like
a = [{'key1':1, 'key2':2, 'key3':3, 'count': 2},
{'key1':1, 'key2':2, 'key3':4, 'count': 0},
{'key1':3, 'key2':2, 'key3':4, 'count': 0}]
i did tryed simple aprouch such as which didnt worked:
a = [{'key1':1, 'key2':2, 'key3':3, 'count': 0},
{'key1':1, 'key2':2, 'key3':4, 'count': 0},
{'key1':3, 'key2':2, 'key3':4, 'count': 0},
{'key1':1, 'key2':2, 'key3':3, 'count': 0}]
for i in range(len(a)):
for n in range(len(a)):
if a[i]['key1'] == a[n]['key1'] and a[i]['key2'] == a[n]['key2'] and a[i]['key3'] == a[n]['key3']:
a[i]['count'] += 1
del a[n]
was thinking aswell there should be some simpler aprouch. thanks
You can leverage Counter method in the collections module.
import collections
count = collections.Counter([tuple(d.items()) for d in a])
[dict(k) | {c:v} for (*k, (c,_)), v in count.items()]
this looks like:
[{'key1': 1, 'key2': 2, 'key3': 3, 'count': 2},
{'key1': 1, 'key2': 2, 'key3': 4, 'count': 1},
{'key1': 3, 'key2': 2, 'key3': 4, 'count': 1}]
If I have two different dictionaries I have created from Queries of different sizes
dictionary1:
{'id': 1 , 'passCount': 3}, {'id': 2 , 'passCount': 4}, {'id': 5 , 'passCount': 7}, {'id': 6, 'passCount': 3}
dictionary2:
{'id': 1 , 'failCount': 1}, {'id': 3 , 'failCount': 2}, {'id': 5 , 'failCount': 3}
Originally, I created a master list from these two dictionaries:
List = []
for i in dictionary1:
for j in dictionary2:
if i['id'] = j['id]:
List.append[i['id'],i['passCount'],j['failCount']]
else:
List.append[i['id'],i['passCount'],0]
List.append[j['id'],0, j['failCount']
return List
When I would print this List out for my data, I would only get a List of id's that match, and would not take into account the other ones.
For that reason I want to print a dictionary where I could get it to print
{'id' = 1, 'passCount' = 3, 'failCount' = 1}, {'id': 2 , 'passCount': 4, 'failCount' = 0}... and so on without deleting any of the id's
Thanks
Short solution using dict.setdefault and dict.update methods:
l1 = [{'id': 1 , 'passCount': 3}, {'id': 2 , 'passCount': 4}, {'id': 5 , 'passCount': 7}, {'id': 6, 'passCount': 3}]
l2 = [{'id': 1 , 'failCount': 1}, {'id': 3 , 'failCount': 2}, {'id': 5 , 'failCount': 3}]
grouped = {}
for d in l1+l2:
grouped.setdefault(d['id'], {'failCount':0, 'passCount': 0}).update(d)
result = [d for d in grouped.values()]
print(result)
The output:
[{'passCount': 3, 'id': 1, 'failCount': 1}, {'passCount': 4, 'id': 2, 'failCount': 0}, {'passCount': 0, 'id': 3, 'failCount': 2}, {'passCount': 7, 'id': 5, 'failCount': 3}, {'passCount': 3, 'id': 6, 'failCount': 0}]
Maybe they're two different lists ,not dictionaries,so I assume they're two lists:
failCount set to 0 by default,you can try this:
a=[{'id': 1 , 'passCount': 3}, {'id': 2 , 'passCount': 4}, {'id': 5 , 'passCount': 7}, {'id': 6, 'passCount': 3}]
b=[{'id': 1 , 'failCount': 1}, {'id': 3 , 'failCount': 2}, {'id': 5 , 'failCount': 3}]
for j in a:
j.update({'failCount': 0})
for i in b:
if i["id"]==j["id"]:
j.update(i)
print(a)
Output:
[{'id': 1, 'passCount': 3, 'failCount': 1}, {'id': 2, 'passCount': 4, 'failCount': 0}, {'id': 5, 'passCount': 7, 'failCount': 3}, {'id': 6, 'passCount': 3, 'failCount': 0}]
I have a list of id's sorted in a proper oder:
ids = [1, 2, 4, 6, 5, 0, 3]
I also have a list of dictionaries, sorted in some random way:
rez = [{'val': 7, 'id': 1}, {'val': 8, 'id': 2}, {'val': 2, 'id': 3}, {'val': 0, 'id': 4}, {'val': -1, 'id': 5}, {'val': -4, 'id': 6}, {'val': 9, 'id': 0}]
My intention is to sort rez list in a way that corresponds to ids:
rez = [{'val': 7, 'id': 1}, {'val': 8, 'id': 2}, {'val': 0, 'id': 4}, {'val': -4, 'id': 6}, {'val': -1, 'id': 5}, {'val': 9, 'id': 0}, {'val': 2, 'id': 3}]
I tried:
rez.sort(key = lambda x: ids.index(x['id']))
However that way is too slow for me, as len(ids) > 150K, and each dict actually had a lot of keys (some values there are strings). Any suggestion how to do it in the most pythonic, but still fastest way?
You don't need to sort because ids specifies the entire ordering of the result. You just need to pick the correct elements by their ids:
rez_dict = {d['id']:d for d in rez}
rez_ordered = [rez_dict[id] for id in ids]
Which gives:
>>> rez_ordered
[{'id': 1, 'val': 7}, {'id': 2, 'val': 8}, {'id': 4, 'val': 0}, {'id': 6, 'val': -4}, {'id': 5, 'val': -1}, {'id': 0, 'val': 9}, {'id': 3, 'val': 2}]
This should be faster than sorting because it can be done in linear time on average, while sort is O(nlogn).
Note that this assumes that there will be one entry per id, as in your example.
I think you are on the right track. If you need to speed it up, because your list is too long and you are having quadratic complexity, you can turn the list into a dictionary first, mapping the ids to their respective indices.
indices = {id_: pos for pos, id_ in enumerate(ids)}
rez.sort(key = lambda x: indices[x['id']])
This way, indices is {0: 5, 1: 0, 2: 1, 3: 6, 4: 2, 5: 4, 6: 3}, and rez is
[{'id': 1, 'val': 7},
{'id': 2, 'val': 8},
{'id': 4, 'val': 0},
{'id': 6, 'val': -4},
{'id': 5, 'val': -1},
{'id': 0, 'val': 9},
{'id': 3, 'val': 2}]
What better way (most elegant) to count the number of items {'id': n}?
'childs': {
1: [{'id': 1}, {'id': 2}, {'id': 3}],
2: [{'id': 4}],
3: [{'id': 5}, {'id': 6},]
}
>>> 6
You should answer to the comments to have a proper answer.
In the meantime, with d being the dict, I'd go with:
sum(len(x) for x in d['childs'].itervalues())
If you don't want to use for, you can do:
sum(map(len, d['childs'].itervalues()))
Or a twisted:
reduce(lambda x, y: x + len(y), d['childs'].itervalues(), 0)
But really the first version is how you would do it. It's classic Python.
As far as I understood your problem, the main task is to count the total occurrence of key "id" whenever it has value of "n". Here the dictionary name is "Childs".
count = 0
for key,value in Childs.iteritems():
if Childs[key]["id"]:
count += 1
print count
Hope it helps!!
cat = {1: [{'id': 1}, {'id': 2}, {'id': 3}], 2: [{'id': 4}], 3: [{'id': 5}, {'id': 6},]}
sum(len(x) for x in cat.values())
myDict = {'childs': {
1: [{'id': 1}, {'id': 2}, {'id': 3}],
2: [{'id': 4}],
3: [{'id': 5}, {'id': 6},]
}}
count = 0
for key in myDict["childs"]:
for item in myDict["childs"][key]:
if checkIfItemIsValid(item):
count += 1
print count
d = {
1: [{'id': 1}, {'id': 2}, {'id': 3}],
2: [{'id': 4}],
3: [{'id': 5}, {'id': 6},]
}
sum(len(i) for i in d.itervalues())
# 6
But this assumes that every member of that child value list is actually an item you want to count.
Here is one other way without using for:
sum(map(len, d.itervalues()))
In case some items may not have the 'id' key and you are only trying to count those which have that key:
sum(1 for obj in i for i in d.itervalues() if 'id' in obj)
or
len([obj for obj in i for i in d.itervalues() if 'id' in obj])
I am trying to replace list element value with value looked up in dictionary how do I do that?
list = [1, 3, 2, 10]
d = {'id': 1, 'val': 30},{'id': 2, 'val': 53}, {'id': 3, 'val': 1}, {'id': 4, 'val': 9}, {'id': 5, 'val': 2}, {'id': 6, 'val': 6}, {'id': 7, 'val': 11}, {'id': 8, 'val': 89}, {'id': 9, 'val': 2}, {'id': 10, 'val': 4}
for i in list:
for key, v in d.iteritems():
???
???
so at the end I am expecting:
list = [30, 1, 53, 4]
thank you
D2 = dict((x['id'], x['val']) for x in D)
L2 = [D2[x] for x in L]
td = (
{'val': 30, 'id': 1},
{'val': 53, 'id': 2},
{'val': 1, 'id': 3},
{'val': 9, 'id': 4},
{'val': 2, 'id': 5},
{'val': 6, 'id': 6},
{'val': 11, 'id': 7},
{'val': 89, 'id': 8},
{'val': 2, 'id': 9},
{'val': 4, 'id': 10}
)
source_list = [1, 3, 2, 10]
final_list = []
for item in source_list:
for d in td:
if d['id'] == item:
final_list.append(d['val'])
print('Source : ', source_list)
print('Final : ', final_list)
Result
Source : [1, 3, 2, 10]
Final : [30, 1, 53, 4]