Nested list with dictionary as content - python

Hi how can I loop through lst2 below, and get the dictionary elements in lst1 if the elements are a match.
lst1 = [[(10, 70, {'a': 0.30}),
(12, 82, {'b': 0.35})],
[(11, 140, {'c': 0.54}),
(99, 25, {'d': 0.57})]
]
lst2 = [[(10, 70), (32, 25),(12,82)],
[(1598, 6009), (11,140), (33,66), (99,25)]
]
ie compare lst2 and if lst2 is in lst1 print the dictionary.
outcome should look like so:
outcome = [[{'a': 0.30}, {'b':0.35}], [{'c': 0.54}, {'d':0.57}]]
Thanks
Sorry an update on this one would be if lst1 is not nested ie
lst1 = [(10, 70, {'a': 0.30}),
(12, 82, {'b': 0.35}),
(11, 140, {'c': 0.54}),
(99, 25, {'d': 0.57})
]
lst2 = [[(10, 70), (32, 25),(12,82)],
[(1598, 6009), (11,140), (33,66), (99,25)]
]
such that the same outcome will be arrived at

You can flatten lst1 and convert that to a dictionary with dictionary comprehension, so that the lookups will be faster. Once the dictionary is constructed, you just have to iterate lst2 and if the element is a key in the dictionary, then get the corresponding dictionary value.
from itertools import chain
d = {(item[0], item[1]):item[2] for item in chain.from_iterable(lst1)}
print d
# {(12,82):{'b':0.3}, (10,70):{'a':0.3}, (11,140):{'c':0.54}, (99,25):{'d':0.57}}
print [[d[item] for item in items if item in d] for items in lst2]
# [[{'a': 0.3}, {'b': 0.3}], [{'c': 0.54}, {'d': 0.57}]]
If the input is not nested, like in the updated question, you don't need chaining. You can simply do
d = {(item[0], item[1]):item[2] for item in lst1}

For each pair, create a dict for the elements from lst1 (for performance) and then check for each of the elements from lst2.
outcome = []
for lst_a, lst_b in zip(lst1, lst2):
lookup = {a[:-1]:a[-1] for a in lst_a}
outcome.append([lookup[b] for b in lst_b if b in lookup])
print outcome

Related

assign elements from a list of list to a dictionary

i have this code:
list1 = [['player1', 5,1,300,100, ..., n],['player2', 10,5,650,150,...n],['player3', 17,6,1100,1050...,n]]
dictionary = {
'playersname':[]
'totalwin':[]
'totalloss':[]
'moneywon':[]
'moneyloss':[]
}
for x in listplayers:
dictionary['name'].append(x[0])
dictionary['totalwins'].append(x[1])
dictionary['totalloss'].append(x[2])
dictionary['moneywon'].append(x[3])
dictionary['moneylost'].append(x[4])
my output:
dictionary = {
'name': [player1,player2,player3,...,n],
'totalwin':[5,10,17,...,n],
'totalloss':[1,5,6],
'moneywon':[300,650,1100],
'moneyloss':[100,150,1050],
}
it works just fine, but i have to write out every dictionary keys and append every items individually
(ex:dictionary['totalwins'].append(x[1]))
so if i had a dictionary with 30 keys and a list with 30 different players caracteristics(ex:win, lost, etc) i would have to write 30 lines.
Is there a way to write the same code in fewer lines (ex:loop through everything) instead of writing 30 lines like so:
1 for x in listplayers:
2 dictionary['name'].append(x[0])
3 dictionary['totalwins'].append(x[1])
... ...
30 dictionary['key30'].append(x[30])
If you make a list of keys, you can zip up the values, then zip that up with the key passing the whole thing to dict()
listplayers = [['player1',5,1,300,100], ['player2',10,5,650,150], ['player3',17,6,1100,1050]]
keys = ['playersname','totalwins','totalloss','moneywon','moneylost']
dictionary = dict(zip(keys, zip(*listplayers)))
dictionary
# {'playersname': ('player1', 'player2', 'player3'),
# 'totalwins': (5, 10, 17),
# 'totalloss': (1, 5, 6),
# 'moneywon': (300, 650, 1100),
# 'moneylost': (100, 150, 1050)}
Notice, this give you tuples, not lists. If that's a problem, you can wrap the zips in a dict comprehension or use map to convert them:
dictionary = {key: list(values) for key, values in zip(keys, zip(*listplayers))}
or
dictionary = dict(zip(keys, map(list,zip(*listplayers))))
You could do the following.
list1 = [['player1', 5,1,300,100],['player2', 10,5,650,150]]
dictionary = {f'key_{i}':[*x] for i,x in enumerate(zip(*list1))}
The resulting dictionary:
{'key_0': ['player1', 'player2'],
'key_1': [5, 10],
'key_2': [1, 5],
'key_3': [300, 650],
'key_4': [100, 150]}
Or, if you have some key names in mind:
list1 = [['player1', 5,1,300,100],['player2', 10,5,650,150]]
keys = ['playersname',
'totalwin',
'totalloss',
'moneywon',
'moneyloss']
{keys[i]:[*x] for i,x in enumerate(zip(*list1))}
The result:
{'playersname': ['player1', 'player2'],
'totalwin': [5, 10],
'totalloss': [1, 5],
'moneywon': [300, 650],
'moneyloss': [100, 150]}

Convert list of lists to unique dictionary in python

I have the following list of lists: [[100, 23], [101, 34], [102, 35] ... ]
How can i convert it to a dictionary like that: {100: 23, 101: 34, 102: 35 ... }
Here is what i tried:
myDict = dict(map(reversed, myList))
This code works, but it will give the opposite of what i want in the dictionary: {23: 100, 101:34..}
You can pass a list with this format to dict() and it will convert it for you.
myList = [[100, 23], [101, 34], [102, 35]]
myDict = dict(myList)
print(myDict)
According to docs page for dict()
. . . the positional argument must be an iterable object. Each item in the iterable must itself be an iterable with exactly two objects. The first object of each item becomes a key in the new dictionary, and the second object the corresponding value.
and here is an example for the same doc page:
...
>>> d = dict([('two', 2), ('one', 1), ('three', 3)])
returns a dictionary equal to {"one": 1, "two": 2, "three": 3}
L = []
A = {}
for x,y in L:
A[x] = y

How to aggregate values from a list of tuples and store them in a dictionary? [duplicate]

This question already has answers here:
How to sum values of tuples that have same name in Python
(4 answers)
Closed 4 years ago.
INPUT:
list = [("a",1),("b",2),("c",3),("a",4),("b",5),("c",6)]
This is the OUTPUT I am looking for:
d = {"a":5,"b":7,"c":9}
Iterate through the list; as a tuple, the first object [0] is your letter, the second [1] is the number. It tries to add the number. If the key isn't created yet (first time seeing the letter) it creates it.
d = {}
list = [("a",1),("b",2),("c",3),("a",4),("b",5),("c",6)]
for i in list:
try:
d[i[0]] += i[1]
except KeyError:
d[i[0]] = i[1]
print(d)
Output:
{'a': 5, 'b': 7, 'c': 9}
You can use collections.defaultdict and a loop:
from collections import defaultdict
lst = [('a', 1), ('b', 2), ('c', 3), ('a', 4), ('b', 5), ('c', 6)]
d = defaultdict(int)
for item in lst:
d[item[0]] += item[1]
print(dict(d)) # {'a': 5, 'b': 7, 'c': 9}
On a side note, don't name your variable list to avoid shadowing the built-in function with the same name.
Alternative without dependencies
res_ = {}
for e in mlist:
if e[0] in res_: res_[e[0]] += e[1]
else: res_[e[0]] = e[1]
print(res_)
#=> {'a': 5, 'c': 9, 'b': 7}

How to change list values in dictionary in python?

I have a dictionary like this,
{'A':[[1,30],[40,50],[60,79]]
'B':[[2,23],[26,43],[59,119]]
'C':[[1,100],[149,167],[199,250]]
... }
I had the MAX value which is 600. Is it possible to calculate the difference between each value in every list?
Finally, I can get a dictionary like this
{'A':[[31,39],[51,59],[80,600]]
'B':[[24,25],[44,58],[120,600]]
'C':[[101,148],[168,198],[251,600]]
...
}
Let me explain how final output comes.
The origin data is
'A':[[i1,i2],[i3,i4],[i5,i6]]
Max value is M,
For each list, final output will be like
'A':[[(i2)+1,(i3)-1],[(i4)+1,(i5)-1],[(i6)+1,M]]
It seems I need a for loop to get there. But I have no idea how to do this in dictionary.
You can try this:
d1 = {'A':[[1,30],[40,50],[60,79]],
'B':[[2,23],[26,43],[59,119]],
'C':[[1,100],[149,167],[199,250]]}
def split_l(iterable, n):
return [iterable[i:i+n] for i in range(0, len(iterable), n)]
d2 = {k:split_l([val + (-1)**idx for idx, val in enumerate(sum(v, [])[1:])] + [600], 2) for k,v in d1.items()}
Or in more readable way:
d2 = {}
for k, v in d1.items():
flat_v = sum(v, [])[1:]
for idx, __ in enumerate(flat_v):
flat_v[idx] += (-1)**idx
flat_v.append(600)
split_v = [flat_v[i:i+2] for i in range(0, len(flat_v), 2)]
d2[k] = split_v
Results:
import pprint
pprint.pprint(d2)
{'A': [[31, 39], [51, 59], [80, 600]],
'B': [[24, 25], [44, 58], [120, 600]],
'C': [[101, 148], [168, 198], [251, 600]]}
YOu can you itertools.chain
>>> from itertools import chain
>>> d = {'A':[[1,30],[40,50],[60,79]], 'B':[[2,23],[26,43],[59,119]],}
>>> for key in d:
... d[key] = zip(*[iter([each+((-1)**index) for index,each in enumerate(chain.from_iterable(d[key]))]+[600,])]*2)
...
>>> d
{'A': [(31, 39), (51, 59), (80, 600)], 'B': [(24, 25), (44, 58), (120, 600)]}
That is,
>>> chain.from_iterable(d['A'])
<itertools.chain object at 0x7f6a9dd69950>
>>> list(chain.from_iterable(d['A']))
[31, 39, 51, 59, 80, 600]
>>> iter(each for each in enumerate(chain.from_iterable(d[key])))
<generator object <genexpr> at 0x7f6a9dd804b0>
>>> zip(*[iter(each for each in enumerate(chain.from_iterable(d[key])))]*2)
[((0, 2), (1, 23)), ((2, 26), (3, 43)), ((4, 59), (5, 119))]
keep in mind that in python you can swap values of two variables this way:
a, b = b, a
so your problem can be solved like this:
def my_func(a_dict, max):
for row in a_dict.values():
row[0][0], row[0][1], row[1][0], row[1][1], row[2][0], row[2][1] = \
row[0][1]+1, row[1][0]-1, row[1][1]+1, row[2][0]-1, row[2][1]+1, max
One thing to notice is that there is no return .... dictionary is mutable, so any change to a_dict will retain.
After calling my_func, the dictionary passed to the function will contain the result.
update
#MaximTitarenko told me that the number of inner lists in each row(row=a list associated with a key of the dictionary)may vary.
so I wrote another script which works in that case:
def make_result(a_dict, max):
for row in a_dict.values():
for index in range(len(row)-1):
row[index][0] = row[index][1] + 1
row[index][1] = row[index+1][0] -1
row[-1][0] = row[-1][1] + 1
row[-1][1] = max

Making a list of dictionaries from a list of tuples

I'm a Python newbie. As a fun exercise, I thought I would create a list of dictionaries from a list of tuples. Little did I know I would bang my head against the wall for hours.
boys = [("Joe", 7, 125), ("Sam", 8, 130), ("Jake", 9, 225)]
keys = ("Name","Height","Weight")
boyz = []
for x in boys:
z = dict(zip(keys,boys[x]))
boyz.append(z)
print(boyz)
When the x in "boys[x]" is replaced with a integer, it works great, but replacing it with a variable within the for loop won't work. WHY?? I'd love an answer to that specifically. But also if there's a more concise to write this whole thing, please let me know.
In each iteration of the for x in boys loop, x will be the value of the next tuple in the list. It is not an integer you can use as an index. Use x instead of boys[x] in the zip to get the result you want.
for x in boys:
z = dict(zip(keys,x))
boyz.append(z)
You are using boys[x] instead of x.
This raises the error:
TypeError: list indices must be integers, not tuple
Here is your edited code:
boys = [("Joe", 7, 125), ("Sam", 8, 130), ("Jake", 9, 225)]
keys = ("Name","Height","Weight")
boyz = []
for x in boys:
z = dict(zip(keys,x))
boyz.append(z)
print(boyz)
This runs as:
>>> boys = [("Joe", 7, 125), ("Sam", 8, 130), ("Jake", 9, 225)]
>>> keys = ("Name","Height","Weight")
>>> boyz = []
>>> for x in boys:
... z = dict(zip(keys,x))
... boyz.append(z)
...
>>> print(boyz)
[{'Name': 'Joe', 'Weight': 125, 'Height': 7}, {'Name': 'Sam', 'Weight': 130, 'Height': 8}, {'Name': 'Jake', 'Weight': 225, 'Height': 9}]
>>>
boys is a list. lists only support indices that are integers but you're passing in a tuple. You'll want to use x as the tuple.
Ultimately, your goal is to get an iterable of keys and values to pass in to zip.
dict(zip(keys, values))
A more concise version, as you asked, can be achieved using list comprehension.
boyz = [dict(zip(keys, boy)) for boy in boys]
Generally, when you see the pattern of creating an empty list, iterating over some iterable and appending its values after map / filtering, you can use a list comprehension instead.
This:
new_list = []
for item in iterable:
if condition(item):
new_value = mapping(item)
new_list.append(new_value)
Is equivalent to:
new_list = [mapping(item) for item in iterable if condition(item)]

Categories