Reputation: 307
While creating a dictionary from the list, the keys of the dictionary neglects the identical items in the List and stores the last item as the key.
For example in this:
lst1 = [["Apple",20.00,"Swiss"],
["Banana",5.00,"Brazil"],
["Strawberry",25.00,"Swiss"],
["Pear",12.00,"Greece"],
["Mango",3.00,"Peru"],
["Avacado",7.00,"Peru"]]
my_dict = {val[2]:val[:2] for val in lst1}
print (my_dict)
Prints this
{'Swiss': ['Strawberry', 25.0], 'Brazil': ['Banana', 5.0], 'Greece': ['Pear', 12.0], 'Peru': ['Avacado', 7.0]}
As far as I understand it does so because the keys can't be identical, then why doesn't it group the values of identical keys in to one list. Like this
{
'Swiss': [["Apple",20.00],['Strawberry', 25.0]],
'Brazil': ['Banana', 5.0],
'Greece': ['Pear', 12.0],
'Peru': [["Mango",3.00],['Avacado', 7.0]]
}
Is there any way I could do this in pure Python?
Upvotes: 2
Views: 65
Reputation: 20414
As far as I am aware, this can't be done in a comprehension
, but you can use setdefault
to make every 2nd element of each list in lst1
a key
in a dictionary
which you can then immediately append
the slice up to it (as you were doing). The neatness of setdefault
is that we can append to a key
if it is already there, or create that key
and then append if it is not. Both actions being done without an if-statement
.
d = {}
for l in lst1:
d.setdefault(l[2], []).append(l[:2])
giving:
{'Brazil': [['Banana', 5.0]],
'Greece': [['Pear', 12.0]],
'Swiss': [['Apple', 20.0], ['Strawberry', 25.0]],
'Peru': [['Mango', 3.0], ['Avacado', 7.0]]}
Upvotes: 3
Reputation: 1121584
You can't use a dictionary comprehension for this, that can't know about preceding keys already being present.
You'll have to use a straight-up loop. Add all values to a list, not just the repeating ones. Don't mix structures here, that'll only create more headaches later on. If you don't you'll have to detect if you have a nested list or a flat list with one fruit and price later on.
You can use a regular dictionary:
my_dict = {}
for fruit, price, origin in lst1:
my_dict.setdefault(origin, []).append([fruit, price])
The dict.setdefault()
call adds an empty list to the dictionary if the key (the first argument) is missing. It then returns the value for the given key (which could be an already existing list or the new empty list). The line then call list.append()
to add the fruit and price.
Or you can use a collections.defaultdict()
object to create the empty lists when a key is missing:
from collections import defaultdict
my_dict = defaultdict(list)
for fruit, price, origin in lst1:
my_dict[origin].append([fruit, price])
Code using a defaultdict
is a little more concise, but the downside is that this object will now continue to produce empty lists for missing keys, even when you perhaps didn't intend to due to a bug in your code.
Both produce the desired result:
>>> my_dict = {}
>>> for fruit, price, origin in lst1:
... my_dict.setdefault(origin, []).append([fruit, price])
...
>>> my_dict
{'Swiss': [['Apple', 20.0], ['Strawberry', 25.0]], 'Brazil': [['Banana', 5.0]], 'Greece': [['Pear', 12.0]], 'Peru': [['Mango', 3.0], ['Avacado', 7.0]]}
>>> from collections import defaultdict
>>> my_dict = defaultdict(list)
>>> for fruit, price, origin in lst1:
... my_dict[origin].append([fruit, price])
...
>>> my_dict
defaultdict(<class 'list'>, {'Swiss': [['Apple', 20.0], ['Strawberry', 25.0]], 'Brazil': [['Banana', 5.0]], 'Greece': [['Pear', 12.0]], 'Peru': [['Mango', 3.0], ['Avacado', 7.0]]})
Upvotes: 4
Reputation: 140168
Those kind of "accumulation" problems cannot be done simply with list comprehensions (or with ugly side effects which impair readability).
You want collections.defaultdict(list)
to create a list of couples as values, and country as key:
lst1 = [["Apple",20.00,"Swiss"],
["Banana",5.00,"Brazil"],
["Strawberry",25.00,"Swiss"],
["Pear",12.00,"Greece"],
["Mango",3.00,"Peru"],
["Avacado",7.00,"Peru"]]
result = collections.defaultdict(list)
for fruit,price,country in lst1:
result[country].append([fruit,price])
print(dict(result)) # convert to dict for a cleaner representation when printing
result:
{'Swiss': [['Apple', 20.0], ['Strawberry', 25.0]], 'Brazil': [['Banana', 5.0]], 'Greece': [['Pear', 12.0]], 'Peru': [['Mango', 3.0], ['Avacado', 7.0]]}
Upvotes: 3