assign elements from a list of list to a dictionary - python

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]}

Related

Adapting the same sorting order from a list

I have a list containing numbers and one containing users. The first element of the first list belongs to the first element of the second list and so on. I then want to sort the number list using sort() and want the usernames to still match with the numbers they had before.
from:
users = ["max", "david", "freddy"]
numbers = [9, 3, 10]
to:
users = ["david", "max", "freddy"]
numbers = [3, 9, 10]
You could use a list comprehension along with zip and sorted:
>>> users = ["max", "david", "Freddy"]
>>> numbers = [9, 3, 10]
>>> sorted_users = [u for _, u in sorted(zip(numbers, users)]
>>> sorted_users
['david', 'max', 'freddy']
You can zip the two into one list, sort based on the number, then unzip them:
users = ["max", "david", "freddy"]
numbers = [9, 3, 10]
zipped = sorted(zip(numbers, users), key=lambda x: x[0])
numbers, users = zip(*zipped)
I would suggest grouping your values together in a list of tuples or dictionaries:
data = [
('max', 9),
('david', 3),
('freddy', 10)
]
and then you can use custom sorting to sort this list:
data.sort(key=lambda x: x[1])
This way your data is stored in a way which keeps their relationship.
To use dictionaries instead requires this simple change:
data = [
{'name': 'max', 'number': 9},
{'name': 'david', 'number': 3},
{'name': 'freddy', 'number': 10}
]
and then change your sort code to
data.sort(key=lambda x: x['number'])
Using the right combination of zip and map, you can do this in one line:
users = ["max", "david", "freddy"]
numbers = [9, 3, 10]
numbers,users = map(list,zip(*sorted(zip(numbers,users))))
print(users) # ['david', 'max', 'freddy']
print(numbers) # [3, 9, 10]
You could try a dictionary for user numbers and user names
users = ["max", "david", "freddy"]
numbers = [9, 3, 10]
dictionary = {users[i]: numbers[i] for i in range(len(numbers))}
{'max': 9, 'david': 3, 'freddy': 10}
and then sort the dictionary and convert back to lists. \

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

What is the quickest way to map between lists in python

I have pairs of 4 lists a and b with integer values such as list_1a = [1,2,3,...] and list_1b = [8,11,15,...]. The idea is that the integer values in list_1a are now represented by the integer values in list_1b, and the same for list_2a and list_2b etc.
Now I have a list of 4 columns final_list which contained integer values corresponding to the a lists. I want to map the values in final_list to the values in the b lists. What is the quickest way to do this in python ?
Is there a quicker way than using lists ?
Edit:
To clarify the question, take the following example:
list_1a = [1,2,3]
list_1b = [8,11,15]
list_2a = [5,6,7,8]
list_2b = [22,26,30,34]
list_3a = [11,12,13,14,18]
list_3b = [18,12,25,28,30]
list_4a = [51,61,72,82]
list_4b = [73,76,72,94]
Note that some of these lists can contain more than a million entries (So maybe memory can be an issue)
The lists do not have the same length
All of the integer values in these lists are unique to their lists, i.e. list_1a + list_1b will never have a repeating integer value.
final_list should look like final_list_b after the mapping occurs
final_list_a = [[1,6,11,51],[3,6,14,72]]
final_list_b = [[8,26,18,73],[15,26,28,72]]
To put things into perspective, this questions is for a database application where these "lists" contain auto-generated key values
I think what you want is a dictionary, which associates keys with values. Unless i'm confused about what you want to do here.
So if I make 4 short example lists.
list_1a = [1,2,3,4]
list_1b = [8,11,15,18]
list_2a = [5,6,7,8]
list_2b = [22,26,30,34]
and make them into a big list of all "a" values and all "b" values.
a_list = list_1a + list_2a
b_list = list_1b + list_2b
I can then use zip to merge the lists into a dictionary
my_dict = dict(zip(a_list, b_list))
print(my_dict)
See:
how to merge 2 list as a key value pair in python
for some other ways to do this last bit.
result:
{1: 8, 2: 11, 3: 15, 4: 18, 5: 22, 6: 26, 7: 30, 8: 34}
Now your "a" list makes up the keys of this dictionary.. while the "b" list make up the values. You can access the values by using the keys. here's some examples.
print(my_dict.keys())
print(my_dict.values())
print(my_dict[5])
gives me:
[1, 2, 3, 4, 5, 6, 7, 8]
[8, 11, 15, 18, 22, 26, 30, 34]
22
Is this what you want?
EDIT: I feel that I should note that while my dictionary has printed in order, dictionaries are actually not ordered like lists. You might want to look into collections.OrderedDict or sorted if this is important to you.
Update:
For what you want to do, maybe consider nested dictionaries. You can make a dictionary whose values are dictionaries, also note that when 1a and 1b don't match in length, zip doesn't care and just excludes 60:
list_1a = [1,2,3,4]
list_1b = [8,11,15,18,60]
list_2a = [5,6,7,8]
list_2b = [22,26,30,34]
a_dict = dict(zip(list_1a, list_2a))
b_dict = dict(zip(list_1b, list_2b))
my_dict = {"a" : a_dict, "b" : b_dict}
print(my_dict)
Result:
{'a': {1: 5, 2: 6, 3: 7, 4: 8}, 'b': {8: 22, 18: 34, 11: 26, 15: 30}}
Now you can access the inner values in a different way:
print(my_dict["a"].keys())
print(my_dict["a"].values())
print(my_dict["a"][4])
Result:
[1, 2, 3, 4]
[5, 6, 7, 8]
8

Create multidimensional numpy array from specific keys of dictionary

I have dictionary like this:
a = dict(zip( ['k1', 'k2', 'k3', 'k4'],
... [ [1,2,3,4], [10,20,30,40], [100,200,300,400], [1000,2000,3000,4000]])
>>> a
{'k1': [1, 2, 3, 4], 'k2': [10, 20, 30, 40], 'k3': [100, 200, 300, 400], 'k4': [1000, 2000, 3000, 4000]}
What I want to do: get values for several keys and create multidimensional numpy array from them. Something like this:
result = numpy.array( [a[x] for x in ('k1' , 'k3')]
I tried this code:
ar = numpy.array([])
for el in ['k1', 'k3']:
ar = numpy.r_[ar, num_dict[el]]
ar = ar.reshape(2,len(ar)/2)
But are there some built in functions or more elegant ways?
A list of lists is normal input to np.array, so your list comprehension makes sense.
In [382]: [a[x] for x in ['k1','k3']]
Out[382]: [[1, 2, 3, 4], [100, 200, 300, 400]]
Or for the whole dictionary
In [385]: np.array(list(a.values())) # list required in py3
Out[385]:
array([[1000, 2000, 3000, 4000],
[ 1, 2, 3, 4],
[ 10, 20, 30, 40],
[ 100, 200, 300, 400]])
Normally dictionary items are selected one by one as in the comprehension. operator has a convenience class for fetching several keys with one call (I don't think it makes much difference in speed):
In [386]: import operator
In [387]: operator.itemgetter('k1','k3')(a)
Out[387]: ([1, 2, 3, 4], [100, 200, 300, 400])
I don't think the iteration with r_ is a good choice. r_ is just a cover for concatenate. If you must iterate, repeated concatante is slower. It's better to build a list, and make the array at the end (as in the list comprehension).
I need exactly one numpy array from data, so I can't find the way without loops.
I create function:
def loadFromDict( fieldnames, dictionary ):
''' fieldnames - list of needed keys, dictionary - dict for extraction
result - numpy.array size of (number of keys, lengths of columns in dict)'''
ar = numpy.zeros( (len(fieldnames), len(dictionary[fieldnames[0]])) )
for c,v in enumerate(fieldnames,0):
ar[c,:] = dictionary[v]
return ar
In my case dictionary has the same length for all columns. Anyway it is easy to implement either they are different: use [len(v) for v in dictionary.values()] to get all lengths, or find lengths for current keys.

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