list to custom dictionary one liner - python

I have a list:
a = [0,1,2,5]
I want to get output something similar to:
output = [{'i':0,'v':0},{'i':1,'v':0},{'i':2,'v':0},{'i':5,'v':0}]
with one line of code/expression where:
output[indx]['i'] = a[indx]
and:
output[indx]['v'] = 0

Use a list comprehension to produce your output list:
[{'i': i, 'v': 0} for i in a]
This produces a list with the same number of elements as a has, each a dictionary wit hthe 'i' value set to an element from a:
>>> a = [0, 1, 2, 5]
>>> [{'i': i, 'v': 0} for i in a]
[{'v': 0, 'i': 0}, {'v': 0, 'i': 1}, {'v': 0, 'i': 2}, {'v': 0, 'i': 5}]

Related

I am getting different value when printing and appending same variable to a list, Why is that?

The first code gives me the output I want but I want the dct to append to a list so I can use the values later. When I try to do that it gives me a different output. Why?
lst = [{'a' : 1, 'b' : 2, 'c': 3 },{'e' : 1, 'f' : 2, 'g': 3}]
e = 0
while e < len(lst):
for k in lst[e]:
dct = {}
x = lst[e][k]
for key, value in lst[e].items():
lst[e][key] = (value - x)
dct[k] = (lst[e])
print(dct)
e += 1
output(lst) = {'a': {'a': 0, 'b': 1, 'c': 2}}
{'b': {'a': -1, 'b': 0, 'c': 1}}
{'c': {'a': -2, 'b': -1, 'c': 0}}
{'e': {'e': 0, 'f': 1, 'g': 2}}
{'f': {'e': -1, 'f': 0, 'g': 1}}
{'g': {'e': -2, 'f': -1, 'g': 0}}
So the following is what I tried to do to save it in a list
e = 0
lst2 = []
while e < len(lst):
for k in lst[e]:
dct = {}
x = lst[e][k]
for key, value in lst[e].items():
lst[e][key] = (value - x)
dct[k] = (lst[e])
lst2.append(dct)
e += 1
print(lst2)
But the output when I print that list gives me the same value for every key in the different dictionaries.
Output(lst2)= [{'a': {'a': -2, 'b': -1, 'c': 0}},
{'b': {'a': -2, 'b': -1, 'c': 0}},
{'c': {'a': -2, 'b': -1, 'c': 0}},
{'e': {'e': -2, 'f': -1, 'g': 0}},
{'f': {'e': -2, 'f': -1, 'g': 0}},
{'g': {'e': -2, 'f': -1, 'g': 0}}]
If you want to use your existing code, change
lst2.append(dct)
to
lst2.append(dct.copy())
(and to understand why, read up on lists, references, and mutability.)
Or, if you want to rewrite your code, you might use
list_ = [{'a' : 1, 'b' : 2, 'c': 3 },{'e' : 1, 'f' : 2, 'g': 3}]
result = {}
for d in list_:
for key, value in d.items():
result[key] = {k:d[k]-value for k in d}
which gives
>>> print(result)
{'a': {'a': 0, 'b': 1, 'c': 2},
'b': {'a': -1, 'b': 0, 'c': 1},
'c': {'a': -2, 'b': -1, 'c': 0},
'e': {'e': 0, 'f': 1, 'g': 2},
'f': {'e': -1, 'f': 0, 'g': 1},
'g': {'e': -2, 'f': -1, 'g': 0},
}
(and if you're a fan of code-golf, here's a one-liner:)
result = {key: {k:d[k]-value for k in d} for d in list_ for key,value in d.items()}

Find common elements and their frequency in list of dictionaries

I have multiple (~40) lists that contain dictionaries, that I would like to find
which are those list items (in this case dictionaries) that are common in all lists
how many times each unique item appears across all lists.
Some examples of the lists are:
a = [{'A': 0, 'B': 0},
{'A': 0, 'C': 1},
{'D': 1, 'C': 0},
{'D': 1, 'E': 0}]
b = [{'A': 0},
{'B': 0, 'C': 1},
{'D': 1, 'C': 0},
{'D': 1, 'E': 0}]
c = [{'C': 0},
{'B': 1},
{'D': 1, 'C': 0, 'E': 0},
{'D': 1, 'E': 0}]
What I tried so far, it is the following code, but it returned values that were not common in all lists...
def flatten(map_groups):
items = []
for group in map_groups:
items.extend(group)
return items
def intersection(map_groups):
unique = []
items = flatten(map_groups)
for item in items:
if item not in unique and items.count(item) > 1:
unique.append(item)
return unique
all_lists = [a,b,c]
intersection(all_lists)
What I would expect to get as a result would be:
1. {'D': 1, 'E': 0} as a common item in all lists
2. {'D': 1, 'E': 0}, 3
{'D': 1, 'C': 0}, 2
{'A': 0, 'B': 0}, 1
{'A': 0, 'C': 1}, 1
{'A': 0}, 1
{'B': 0, 'C': 1}, 1
{'C': 0},
{'B': 1},
{'D': 1, 'C': 0, 'E': 0}
To count things, python comes with a nice class: collections.Counter. Now the question is: What do you want to count?
For example, if you want to count the dictionaries that have the same keys and values, you can do something like this:
>>> count = Counter(tuple(sorted(x.items())) for x in a+b+c)
>>> count.most_common(3)
[((('C', 0), ('D', 1)), 2), ((('D', 1), ('E', 0)), 2), ((('A', 0), ('B', 0)), 1)]
The dictionaries here are converted to tuples with sorted items to make them comparable and hashable. Getting for example the 3 most common back as a list of dictionaries is also not too hard:
>>> [dict(x[0]) for x in count.most_common(3)]
[{'C': 0, 'D': 1}, {'D': 1, 'E': 0}, {'A': 0, 'B': 0}]
You can use a nested for loop:
a = [{'A': 0, 'B': 0},
{'A': 0, 'C': 1},
{'D': 1, 'C': 0},
{'D': 1, 'E': 1}]
b = [{'A': 0},
{'B': 0, 'C': 1},
{'D': 1, 'C': 0},
{'D': 1, 'E': 0}]
c = [{'C': 0},
{'B': 1},
{'D': 1, 'C': 0, 'E': 0},
{'D': 1, 'E': 0}]
abc_list = [*a, *b, *c]
abc = list()
for d in abc_list:
for i in abc:
if d == i[0]:
abc[abc.index(i)] = (d, i[1] + 1)
continue
abc.append((d, 1))
print(abc)
Output:
[({'A': 0, 'B': 0}, 1),
({'A': 0, 'C': 1}, 1),
({'D': 1, 'C': 0}, 2),
({'D': 1, 'E': 1}, 1),
({'A': 0}, 1),
({'B': 0, 'C': 1}, 1),
({'D': 1, 'E': 0}, 2),
({'C': 0}, 1),
({'B': 1}, 1),
({'D': 1, 'C': 0, 'E': 0}, 1)]
Explanation:
The line
[*a, *b, *c]
unpacks all the values in lists a, b and c into a single list, which \i named abc_list.
The continue statement where I put it means to directly continue to the next iteration of the inner for loop, without reaching abc.append((d, 1)).
The above output answers question 2. For question 1, we can use the built-in max() method on the abc list, with a custom key:
print(max(ABC, key=lambda x:x[1])[0])
Of course, it will only return one dictionary, {'D': 1, 'C': 0}. If you want to print out multiple dictionaries that appear the most frequently:
m = max(abc, key=lambda x:x[1])[1]
for d in abc:
if d[1] == m:
print(d[0])
Output:
{'D': 1, 'C': 0}
{'D': 1, 'E': 0}

Create list with all combination of dictionaries, where key only appears once

I tried different approaces with itertools, but just can't figure it out.
I need to find different combinations of dictionaries:
letters = ['a','b','c']
combinations = []
for i in range(3):
for t in letters:
one_combi = {str(t):i}
combinations.append(one_combi)
Now have a list of dictionaries {letter:number}
Now I need to create a list of combinations where the key (letter) only appear once.
Expected output looks something like this:
[{'a':0,'b':0,'c':0},
{'a':1,'b':0,'c':0},
{'a':1,'b':1,'c':0},
{'a':1,'b':1,'c':1},
{'a':2,'b':0,'c':0},
...
{'a':2,'b':2,'c':2}]
Would be great if someone can help me out on this one!
You can generate all combinations of integers from a range derived from the length of the input, and then use zip:
letters = ['a','b','c']
def combos(d, c = []):
if len(c) == len(d):
yield dict(zip(letters, c))
else:
for i in d:
yield from combos(d, c+[i])
print(list(combos(range(len(letters))))
Output:
[{'a': 0, 'b': 0, 'c': 0},
{'a': 0, 'b': 0, 'c': 1},
{'a': 0, 'b': 0, 'c': 2},
{'a': 0, 'b': 1, 'c': 0},
{'a': 0, 'b': 1, 'c': 1},
...
{'a': 2, 'b': 2, 'c': 2}]
What you are looking for is itertools.product
from itertools import product
lst = []
for a, b, c in product([0, 1, 2], repeat=3):
lst.append({'a': a, 'b': b, 'c': c})
print(lst)
Output:
[{'a': 0, 'b': 0, 'c': 0},
{'a': 0, 'b': 0, 'c': 1},
{'a': 0, 'b': 0, 'c': 2},
{'a': 0, 'b':1, 'c': 0},
{'a': 0, 'b': 1, 'c': 1},
{'a': 0, 'b': 1, 'c': 2},
{'a': 0, 'b': 2, 'c': 0},
{'a': 0, 'b': 2, 'c': 1},...
Update
We can compact everything into a single line using list comprehension.
letters = ['a','b','c']
lst = [dict(zip(letters, x)) for x in product(range(len(letters)), repeat=len(letters))]
print(lst)

Is there any way to sort this dictionaries by lowest value from keys?

I just wanna sort these dictionaries with some values from an input file.
def sortdicts():
listofs=[]
listofs=splitndict()
print sorted(listofs)
The splitndict() function has this output:
[{'a': 1, 'b': 2}, {'c': 2, 'd': 4}, {'a': 7, 'c': 3}, {'y': 5, 'x': 0}]
While the input is from another file and it's:
a 1
b 2
c 2
d 4
a 7
c 3
x 0
y 5
I used this to split the dictionary:
def splitndict():
listofd=[]
variablesRead=readfromfile()
splitted=[i.split() for i in variablesRead]
d={}
for lines in splitted:
if lines:
d[lines[0]]=int(lines[1])
elif d=={}:
pass
else:
listofd.append(d)
d={}
print listofd
return listofd
The output file should look like this:
[{'y': 5, 'x': 0}, {'a': 1, 'b': 2}, {'c': 2, 'd': 4}, {'a': 7, 'c': 3}
This output because :
It needs to be sorted by the lowest value from each dictionary key.
array = [{'y': 5, 'x': 0}, {'a': 1, 'b': 2}, {'c': 2, 'd': 4}, {'a': 7, 'c': 3}]
for the above array:
array = sorted(array, lambda element: min(element.values()))
where "element.values()" returns all values from dictionary and "min" returns the minimum of those values.
"sorted" passes each dictionary (an element) inside the lambda function one by one. and sorts on the basis of the result from the lambda function.
x = [{'y': 5, 'x': 0}, {'a': 1, 'b': 2}, {'c': 2, 'd': 4}, {'a': 7, 'c': 3}]
sorted(x, key=lambda i: min(i.values()))
Output is
[{'y': 5, 'x': 0}, {'a': 1, 'b': 2}, {'c': 2, 'd': 4}, {'a': 7, 'c': 3}]

How can I order a dictionary list by one specified key with some values being None? [duplicate]

This question already has answers here:
How to ignore None values with operator.itemgetter when sorting a list of dicts?
(4 answers)
Closed 3 years ago.
There is a list like
l = [{"n": 1, "m": 3}, {"n": None, "m": 1}, {"n": 3, "m": None}, {"n": None, "m": 0}]
And I want to order it by one specified key, n for example.
Besides, some value of the key may be None, and I want to leave them at behind
Here's my trial
l = [{"n": 1, "m": 3}, {"n": None, "m": 1}, {"n": 3, "m": None}, {"n": None, "m": 0}]
from functools import partial
def order(key, item):
if item[key]:
return item[key]
else:
return 0
order_key = "n"
r = sorted(l, key=partial(order, order_key), reverse=True)
print(r)
Is there a better way to make it happen?
Here's one approach using sorted with a key:
sorted(l, key=lambda x: -x['n'] if x['n'] is not None else float('inf'))
[{'n': 3, 'm': None},
{'n': 1, 'm': 3},
{'n': None, 'm': 1},
{'n': None, 'm': 0}]
Let's check with another example:
l = [ {"n":1, "m":3}, {"n":None, "m":1}, {"n":3, "m":None}, {"n":None, "m":0},
{"n":0, "m":0}, {"n":-1, "m":0}]
sorted(l, key=lambda x: -x['n'] if x['n'] is not None else float('inf'))
[{'n': 3, 'm': None},
{'n': 1, 'm': 3},
{'n': 0, 'm': 0},
{'n': -1, 'm': 0},
{'n': None, 'm': 1},
{'n': None, 'm': 0}]
use a key function that returns a tuple for a double criteria:
l = [ {"n":1, "m":3}, {"n":None, "m":1}, {"n":3, "m":None}, {"n":None, "m":0}]
result = sorted(l,key = lambda d : (d["m"] is None,d["m"] or 0))
result:
>>> result
[{'m': 0, 'n': None},
{'m': 1, 'n': None},
{'m': 3, 'n': 1},
{'m': None, 'n': 3}]
Let's clarify how and why it works:
(d["m"] is None,d["m"] or 0) is a tuple:
True if the value is None for the first element, which guarantees that None entries are last (negate for the reverse effect)
the other one is the tiebreaker, with the or trick to convert None to 0 so it's comparable with other integers without errors (although here it is not needed since first boolean stops the tuple comparison so we could write (d["m"] is None,d["m"]))
l = [ {"n":1, "m":3}, {"n":None, "m":1}, {"n":3, "m":None}, {"n":None, "m":0}]
newlist = sorted(l, key=lambda k: (k['n'] is None, k['n'] == 0, k['n']), reverse = True)
print (newlist)
output:
[{'n': None, 'm': 1}, {'n': None, 'm': 0}, {'n': 3, 'm': None}, {'n': 1, 'm': 3}]

Categories