In python I wish to create a dictionary using a comprehension with keys that are strings, and values that are lists. What I cannot figure out, is how to append elements to these lists. For example consider my following attempt:
{c: [].append(x[0]) for x in g16.nodes(data=True) for c in colors if x[1]['color'] == c}
g16.nodes(data=True) gives a list of pairs where the first element is a string, and the second element is a dictionary which just specifies a color. As stated, I wish to make this structure into a dictionary, where the keys give the color, and the values are lists of strings which have this color.
If you have the solution, or if there is a better way to do this, please let me know!
Thanks for all the help.
You are trying to do this:
{c: [x[0] for x in g16.nodes(data=True) if x[1]['color'] == c] for c in colors}
But it's not very efficient as you are looping over g16.nodes(data=True) once for each color
Something like this is better
d = {c: [] for c in colors}
for x in g16.nodes(data=True):
k = x[1]['color']
if k in d:
d[k].append(x[0])
If you know k is always in colors, you could simplify to
d = {c: [] for c in colors}
for x in g16.nodes(data=True):
d[x[1]['color']].append(x[0])
Using a comprehension for a dictionary of key to lists is not going to be pretty. It's probably easier if you can try this:
Assuming g16.nodes(data=True) is something like
[('key1', {'color': 'black'}), ('key2', {'color': 'green')]
and the color key exists, you can try this:
from collections import defaultdict
gen = ((k, c['color']) for k, c in g16.nodes(data=True) if c['color'] in colors)
results = defaultdict(list)
for key, color in gen:
results[color].append(key)
Related
Here I have a list like this.
ls = ['Small:u', 'Small:o']
What I want is to create a dictionary of each list items like this.
dict1 = {'Small':'u'}
dict2 = {'Small':'o'}
How can I do it ? Is it possible?
>>> x = [dict([pair.split(":", 1)]) for pair in ['Small:u', 'Small:o']]
>>> x
[{'Small': 'u'}, {'Small': 'o'}]
Yes, it is possible, but one thing I'm not sure whether is possible (or a good idea at all) is to programmatically assign variable names to new dictionaries, so instead the easier way is to create a dictionary of dictionaries:
dic_of_dics = {}
for index, item in enumerate(ls):
i, j = item.split(':')
dic_of_dics[f'dict{index}'] = {i : j}
This is another way:
ls = ['Small:u', 'Small:o']
dict_list = []
for i in ls:
k, v = i.split(':')
dict_list.append({k: v})
print(dict_list)
print(dict_list[1].values())
Perhaps with minimal line:
ls = ['Small:u', 'Small:o']
dict_list = map(lambda x:dict([x.split(':')]), ls)
# for python3: print(list(dict_list))
# for Python2: print(dict_list)
Explanation: I am using map function to convert the list of string to list of lists. Then I am passing it through dict(to convert them to dictionary).
I have a dictionary like so
d = {"key_a":1, "anotherkey_a":2, "key_b":3, "anotherkey_b":4}
So the values and key names are not important here. The key (no pun intended) thing, is that related keys share the same suffix in my example above that is _a and _b.
These suffixes are not known before hand (they are not always _a and _b for example, and there are an unknown number of different suffixes.
What I would like to do, is to extract out related keys into their own dictionaries, and have all generated dictionaries in a list.
The output from above would be
output = [{"key_a":1, "anotherkey_a":2},{"key_b":3, "anotherkey_b":4}]
My current approach is to first get all the suffixes, and then generate the sub-dicts one at a time and append to the new list
output = list()
# Generate a set of suffixes
suffixes = set([k.split("_")[-1] for k in d.keys()])
# Create the subdict and append to output
for suffix in suffixes:
output.append({k:v for k,v in d.items() if k.endswith(suffix)})
This works (and is not prohibitively slow or anyhting) but I am simply wondering if there is a more elegant way to do it with a list or dict comprehension? Just out of interest...
Make your output a defaultdict rather than a list, with suffixes as keys:
from collections import defaultdict
output = defaultdict(lambda: {})
for k, v in d.items():
prefix, suffix = k.rsplit('_', 1)
output[suffix][k] = v
This will split your dict in a single pass and result in something like:
output = {"a" : {"key_a":1, "anotherkey_a":2}, "b": {"key_b":3, "anotherkey_b":4}}
and if you insist on converting it to a list, you can simply use:
output = list(output.values())
You could condense the lines
output = list()
for suffix in suffixes:
output.append({k:v for k,v in d.items() if k.endswith(suffix)})
to a list comprehension, like this
[{k:v for k,v in d.items() if k.endswith(suffix)} for suffix in suffixes]
Whether it is more elegant is probably in the eyes of the beholder.
The approach suggested by #Błotosmętek will probably be faster though, given a large dictionary, since it results in less looping.
def sub_dictionary_by_suffix(dictionary, suffix):
sub_dictionary = {k: v for k, v in dictionary.items() if k.endswith(suffix)}
return sub_dictionary
I hope it helps
I have two python dictionaries, and I want to return combinations of the dictionary keys if the keys do not have any values in common with each other.
Sort of like:
for i in 'a':
for j in 'b':
for i.items():
if any.i.items() in any.j.items()
continue
else show me someway to pair all combinations together
Lets say my code is as shown below:
a={'dog':['hungry','fun'],'cat':['ugly','old'],'fish':[1,2,'hungry',4]}
b={'raccoon':['ugly',1,3,], 'bird':[18,'hungry'],'cat':['orange','short']}
This would return
dog+raccoon, dog+cat, cat+bird, cat+cat, fish+cat
because none of these potential pairings have dictionary values in common. If anyone could show me how I would do this I would appreciate it.
You can use sets:
from itertools import product
pairs = set()
for (ak, av), (bk, bv) in product(a.items(), b.items()):
if not set(av).intersection(set(bv)):
pairs.add("%s+%s" % tuple(sorted([ak, bk])))
print pairs
Produces:
set(['bird+cat', 'cat+fish', 'cat+cat', 'cat+dog', 'dog+raccoon'])
This can be more efficient if you have sets instead of lists in the first place.
May be this can get it:
a={'dog':['hungry','fun'],'cat':['ugly','old'],'fish':[1,2,'hungry',4]}
b={'raccoon':['ugly',1,3,], 'bird':[18,'hungry'],'cat':['orange','short']}
result = []
for b_key, b_value in b.iteritems():
for a_key, a_value in a.iteritems():
if not any(x in a_value for x in b_value):
result.append((a_key, b_key))
print(result)
[('dog', 'raccoon'), ('cat', 'bird'), ('fish', 'cat'), ('dog', 'cat'), ('cat', 'cat')]
def no_shared(a,b):
res = []
pairs = [(x, y) for x in a for y in b]
for x,y in pairs:
if set(a[x]) & set(b[y]):
continue
res.append((x, y))
return res
Basically test for any intersection between the lists (as sets) and then skip adding it if they have any intersection.
Also, if the list values are always going to be unique for that entry in that dict (seems so from the example) then storing it initially as a set saves you the conversion.
I have a dictionary that looks like:
myD={'key_0':[[['descrp_0_0'],Obj_0_0],.....,[['descrp_0_N'],obj_0_N]]
,.....,
'key_N':[[['descrp_N_0'],Obj_N_0],.....,[['descrp_N_N'],obj_N_N]]}
All objs are ndarrays of the same shape and have a function f() that returns an x which is a float i.e.:
obj_0_0.f() --> x_0_0
I want to extract a dictionary with the descrp and obj and their respective key where obj.f() (i.e. x) is minimum for the values in each key (at the myD scope of N keys would give N items in shape of [descrp,obj]):
The result must look something like:
resD = {'key_0':[[descrp_0_min],obj_0_min],
.....,
'key_N':[[descrp_N_min],obj_0_min]}
Something like:
minXs = [min([item[-1].f() for item in v]) for k,v in myD.iteritems()]
minObjs = [item for k,v in myD.iteritems() for item in v if item[-1].get_potential_energy() == minXs[myD.keys().index(k)]]
resultList = zip(myD.keys(),minObjs)
resultDict = dict()
for i in resultList:
resultDict[i[0]]=i[1]
Although it works but is rather cumbersome and I think there must be an easier way to do this. Or maybe I should use numpy.ndarray for this purpose?
I appreciate your help and comments.
If I've understood the structure of your data correctly, I think you can solve this with a dictionary comprehension that calls the builtin min function and gives it a key function.
results = {key: min(values, key=lambda x:x[-1].f())
for key, values in myD.iteritems()}
Your code was really close already!
I have a list of dictionaries.
Each dictionary has a colour attribute. For example:
{'att1':value1, 'att2': value2, 'colour': 'Red'}
The colou attribute is from a list of 15 maxium colours.
I have over a thousand of these dictionaries in the list. I need to find out what is the popular colour and how many instances of it there are? Simiilarly I need the second most popular colour, the number of instances of it, the third most, fourth most etc...
Can some fancy pythonic syntax help me out?
from collections import defaultdict
colours = defaultdict(int)
for item in mylist:
colours[item["colour"]] +=1
gives you a defaultdict with all the colours and their respective number. Displaying those in a sorted fashion is trivial.
You could use Counter and generator like this:
distribution = collections.Counter(d['colour'] for d in list_of_dict)
distribution.most_common(2)
Use map to map each dictionary to its colors, then a collections.Counter. Should be a one-liner this way. Something like
collections.Counter(map(lambda x: x.get("color"), listofdict))
l = []
for x in xrange(100):
l.append({'att1':1, 'att2': 2, 'colour': 'Red'})
for x in xrange(10):
l.append({'att1':1, 'att2': 2, 'colour': 'Blue'})
colors = [i['colour'] for i in l]
dcolors = {}
for i in colors:
if not i in dcolors:
dcolors[i] = 0
dcolors[i] += 1
print dcolors
I created 100 red and 10 blue items, the print result is:
{'Blue': 10, 'Red': 100}
You probably can find a way to find the max etc or sort it.