This question already has answers here:
Create a dictionary with comprehension
(17 answers)
Closed 5 years ago.
I am looking for a short and compact one-liner to initialize a dictionary from a list in Python. Is there an equivalent to the two constructs below?
dic = {}
for elt in list:
dic[elt.hash] = elt
.
dic2 = {}
defaultValue = 0
for elt in list:
dic2[elt] = defaultValue
I've see the use of Counter for the second case, but it is a very narrow case, and I'm looking for a generic syntax.
Summary of three pythonic solutions to instantiating dictionaries. Having a "one-line" solution should never be the most important consideration.
1. Keys and default value defined in advance.
Instead of setting a default value for every key, use dict.fromkeys. Also, do not name variables the same as classes, e.g. use lst instead.
dic2 = dict.fromkeys(lst, 0)
2. Default value defined in advance, but not keys.
Alternatively, if you will be adding more keys in the future, consider using collections.defaultdict, which is a subclass of dict:
from collections import defaultdict
dic2 = defaultdict(int)
dic2['newkey'] # returns 0 even not explicitly set
3. Keys and values related by a function.
For building a dictionary where keys and values are linked via a function, use a dictionary comprehension, as described in detail by #OmerB, e.g.
{k: f(k) for k in lst} # value function of given keys
{f(v): v for v in lst} # key function of given values
Well, dictionary comprehension is one-line, is that what you mean?
>> MyList = ['apple', 'banana', 'pear']
>> {hash(element): element for element in MyList}
{-8723846192743330971: 'pear',
-6060554681585566095: 'banana',
-4133088065282473265: 'apple'}
Also - I'm suspecting that using the element's hash as the key is not what you're looking for:
If your elements are immutable (e.g. strings), you could use the elements themselves as keys.
If they're not immutable, you can use the element's location in the list.
For the latter, to make sure you insert each value only once to the dict, clear duplicates from the list before iterating over it:
>> MyList = ['apple', 'apple', 'banana', 'banana', 'pear']
>> {idx: value for (idx,value) in enumerate(set(MyList))}
{0: 'banana', 1: 'pear', 2: 'apple'}
A simple one liner statement for case-01 using dict constructor, map and zip:
>>> l = ['a','b','c']
>>> dict(zip(map(hash,l),l))
>>> {12416037344: 'a', 12672038114: 'c', 12544037731: 'b'}
For second situation:
>>> l = ['a','b','c']
>>> default_value = 10
>>> dict((zip(l,[default_value]*len(l))))
>>> {'a': 10, 'c': 10, 'b': 10}
Those two constructs can be built using dictionary comprehensions like:
Code:
dic_comp = {getattr(elt, 'hash'): elt for elt in test_data}
dic2_comp = {elt: defaultValue for elt in test_data}
Test Code:
class TestObj(object):
def __init__(self, hash_value):
self.hash = hash_value
test_data = [TestObj(i) for i in range(5)]
dic = {}
for elt in test_data:
dic[elt.hash] = elt
dic_comp = {getattr(elt, 'hash'): elt for elt in test_data}
assert dic == dic_comp
dic2 = {}
defaultValue = 0
for elt in test_data:
dic2[elt] = defaultValue
dic2_comp = {elt: defaultValue for elt in test_data}
assert dic2 == dic2_comp
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).
Example code:
my_dict = {'ABC':'Apple','DEF':'Mango','GHI':'Pear','JKL':'Orange','MNO':'Plum'}
lst_x = ['DEF','GHI']
Expected result:
['Mango', 'Pear']
You can retrieve multiple keys at once, by using operator.itemgetter:
from operator import itemgetter
my_dict = {'ABC':'Apple','DEF':'Mango','GHI':'Pear','JKL':'Orange','MNO':'Plum'}
lst_x = ['DEF','GHI']
# in case, if there's a chance, that lst_x would get some of the keys, that are not in my_dict - add the below line:
# lst_x=set(lst_x).intersection(set(my_dict.keys()))
res=itemgetter(*lst_x)(my_dict)
Outputs:
>>> res
('Mango', 'Pear')
You can use a simple loop, ask if there is a key with the same value and print it, for example:
my_dict = {'ABC':'Apple','DEF':'Mango','GHI':'Pear','JKL':'Orange','MNO':'Plum'}
lst = ['ABC','DEF','GHI','JKL','MNO']
for key in lst:
if key in my_dict.keys():
print(key, '->' , my_dict[key])
>>> ABC -> Apple
>>> DEF -> Mango
>>> GHI -> Pear
>>> JKL -> Orange
>>> MNO -> Plum
One approach would be to use a list comprehension to construct the requested list.
Essentially we iterate through the list in the outer loop, and through the dictionary in the inner loop and then we compare the list value with the keyfrom the dictionary, and should we have a match, then we save the value of the associated key in the new output list.
This code snippet below works as described above:
my_dict = {'ABC':'Apple','DEF':'Mango','GHI':'Pear','JKL':'Orange','MNO':'Plum'}
lst_x = ['DEF','GHI']
out = [value for element in lst_x for key, value in my_dict.items() if element == key]
print(out)
When run it prints:
['Mango', 'Pear']
I personally don't believe in giving outright answers so I will give you a hint:
// for x in lst:
// if x in dictionary then
// lst_x.append(x)
I believe that should be enough for you to figure out the rest.
How to create a dictionary from a string composed by space separated words with i for i in range(0, n) as key in the dictionary ?
Tried this:
i = 0
map(dic[i+=1],input().split())
It didn't work.
It should output this:
dic={0:'apple',1:'grapes',2:'orange',3:'banana'}
input_str = "Hello world"
result = {key: value for key, value in enumerate(input_str.split())}
print(result)
Output:
{0: 'Hello', 1: 'world'}
But you can use a list since this data structure is made for iterating over their contents and keeps order. If you want an int as key, just use enumerate(your_list).
In Python, when to use a Dictionary, List or Set?
You could use enumerate:
d = {}
for i, v in enumerate(input().split()):
d[i] = v
Or simply:
d = dict(enumerate(input().split()))
But why do that? use a list...
Since your keys are simply (ordered!) integers, using a dict seems an overkill as to access integer-indexed values from a list is also O(1). For example, let's look at a small comparison with the 2 versions:
l = input().split()
d = dict(enumerate(l))
We have:
>>> print(l)
['apple', 'orange', 'banana']
>>> print(d)
{0: 'apple', 1: 'orange', 2: 'banana'}
Now let's see how we will grab values:
>>> l[0]
'apple'
>>> d[0]
'apple'
>>> l[2]
'banana'
>>> d[2]
'banana'
Dictionaries have a small memory overhead and so for this case using a dictionary doesn't give any advantage.
input_ = input("enter your fruits:").split(' ')
print (dict(zip([*range(len(input_))], input_)))
# print (dict(enumerate(input_)))
output:
enter your fruits:banana kiwi orange apple
{0: 'banana', 1: 'kiwi', 2: 'orange', 3: 'apple'}
Say I have a dictionary with many items that have the same values; for example:
dict = {'hello':'a', 'goodbye':'z', 'bonjour':'a', 'au revoir':'z', 'how are you':'m'}
How would I split the dictionary into dictionaries (in this case, three dictionaries) with the same values? In the example, I want to end up with this:
dict1 = {'hello':'a', 'bonjour':'a'}
dict2 = {'goodbye':'z', 'au revoir':'z'}
dict3 = {'how are you':'m'}
You can use itertools.groupby to collect by the common values, then create dict objects for each group within a list comprehension.
>>> from itertools import groupby
>>> import operator
>>> by_value = operator.itemgetter(1)
>>> [dict(g) for k, g in groupby(sorted(d.items(), key = by_value), by_value)]
[{'hello': 'a', 'bonjour': 'a'},
{'how are you': 'm'},
{'goodbye': 'z', 'au revoir': 'z'}]
Another way without importing any modules is as follows:
def split_dict(d):
unique_vals = list(set(d.values()))
split_dicts = []
for i in range(len(unique_vals)):
unique_dict = {}
for key in d:
if d[key] == unique_vals[i]:
unique_dict[key] = d[key]
split_dicts.append(unique_dict)
return split_dicts
For each unique value in the input dictionary, we create a dictionary and add the key values pairs from the input dictionary where the value is equal to that value. We then append each dictionary to a list, which is finally returned.
I want to use the items in a list as dictionary keys to find a value in nested dictionaries.
For example, given the following list:
keys = ['first', 'second', 'third']
I want to do:
result = dictionary[keys[0]][keys[1]][keys[2]]
Which would be the equivalent of:
result = dictionary['first']['second']['third']
But I don't know how many items will be in the keys list beforehand (except that it will always have at least 1).
Iteratively go into the subdictionaries.
result = dictionary
for key in keys:
result = result[key]
print(result)
A simple for-loop will work:
result = dictionary[keys[0]] # Access the first level (which is always there)
for k in keys[1:]: # Step down through any remaining levels
result = result[k]
Demo:
>>> dictionary = {'first': {'second': {'third': 123}}}
>>> keys = ['first', 'second', 'third']
>>> result = dictionary[keys[0]]
>>> for k in keys[1:]:
... result = result[k]
...
>>> result
123
>>>