What is the most efficient way to create a dictionary from a string/list? For example, if I have a list ['a', 'b', 'c', 'd'], how would I create the dictionary for which the elements of the list are the keys, and the indices are the values? How it would look like for the above list: {'a': 0, 'b': 1, 'c': 2, 'd': 3}
enumerate() will return the elements and their indexes, you can use this in a dictionary comprehension.
l = ['a', 'b', 'c', 'd']
d = {value: index for index, value in enumerate(l)}
you can use this:
lista = ['a', 'b', 'c', 'd']
dictionary = {}
n = 0
for el in lista:
dictionary[el] = n
n += 1
Related
Is there a short way to sort a list based on the order of another dictionary keys?
suppose I have:
lst = ['b', 'c', 'a']
dic = { 'a': "hello" , 'b': "bar" , 'c': "foo" }
I want to sort the list to be ['a','b','c'] based on the order of dic keys.
You can create a lookup of keys versus their insertion order in dic. To do so you can write:
>>> lst = ['d', 'b', 'c', 'a']
>>> dic = {"a": "hello", "b": "bar", "c": "foo"}
>>> order = {k: i for i, k in enumerate(dic)}
>>> order
{'a': 0, 'b': 1, 'c': 2}
Using this you can write a simple lookup for the key argument of sorted to rank items based on order.
>>> sorted(lst, key=order.get)
['a', 'b', 'c']
If there are values in lst that are not found in dic you should call get using a lambda so you can provide a default index. You'll have to choose if you want to rank unknown items at the start or end.
Default to the start:
>>> lst = ['d', 'b', 'c', 'a']
>>> sorted(lst, key=lambda k: order.get(k, -1))
['d', 'a', 'b', 'c']
Default to the end:
>>> lst = ['d', 'b', 'c', 'a']
>>> sorted(lst, key=lambda k: order.get(k, len(order)))
['a', 'b', 'c', 'd']
In Python, how do I convert a list that contains strings and lists that have two values into a dictionary such that the key is the string and the value is a list of lists such that the first value of each list is the key.
For example, the current list I have is:
['A', ['A', 1], 'B', ['B',1], ['B',2], 'C', ['C', 1], ['C',2], ['C',3]]
and I want the dictionary:
{'A': [['A', 1]], 'B': [['B',1], ['B',2]], 'C': [['C',1], ['C',2], ['C',3]]}
Thank you.
EDIT: The number of lists that follow a string is arbitrary.
With this, no matter the order of the list, it selects exactly what you're looking for.
def new(list_):
new_dic = {x:[y for y in list_ if type(y) == list and y[0] == x] for x in list_ if type(x) == str}
print(new_dic)
new(['A', ['A', 1], ['A',2], 'B', ['B',1], ['B',2], 'C', ['C', 1], ['C',2]])
d = {l: [] for l in mylist if type(l) is str}
for l in mylist:
if type(l) is list:
d[l[0]].append(l)
You can try defaultdict
from collections import defaultdict
my_dict = defaultdict(list)
my_list = ['A', ['A', 1], ['A',2], 'B', ['B',1], ['B',2], 'C', ['C', 1], ['C',2]]
for index in my_list:
if len(index) > 1:
my_dict[index[0]].append(index)
It seems like it doesn't matter what the string values are in your list. Based on the current structure of the list provided, and the required output, you can just check for the lists inside the list, and by using the defaultdict construct, you can simply just craft your dictionary accordingly:
from collections import defaultdict
l = ['A', ['A', 1], 'B', ['B',1], ['B',2], 'C', ['C', 1], ['C',2], ['C',3]]
d = defaultdict(list)
for data in l:
if type(data) is list:
d[data[0]].append(data)
Output:
defaultdict(<class 'list'>, {'A': [['A', 1]], 'C': [['C', 1], ['C', 2], ['C', 3]], 'B': [['B', 1], ['B', 2]]})
So, here, the defaultdict will take a list as its default collection value. Therefore, when adding a new key, the default value will be a list. As you iterate over the list, simply check the type of the data in the list. When you find a list, you insert it in to your dictionary taking the first value of that list as the key, and then append the list as the value. It should give you the output you are looking for.
Using the Collection Counter,
l1 = ['a', 'b', 'b', 'c', 'c', 'b', 'e']
l2 = ['a', 'b', 'b', 'c', 'c', 'b','d']
from collections import Counter
c1 = Counter(l1)
c2 = Counter(l2)
# Intersection
c1 & c2
>>> Counter({'b': 3, 'c': 2, 'a': 1})
What idiom could distribute Collections Counter into a list of lists where each multiple appears only once in each list?
[['a', 'b', 'c'],['b', 'c'],['b']]
Don't know if you were looking for a one-liner, but here is a one-liner:
Code:
[sorted(y for y in z if y is not None)
for z in it.izip_longest(*[[k] * l for k, l in c.items()])]
How?
Two key things here:
[k] * l gives a list of the counter keys which is counter values long
izip_longest() will put the lists togther and pad fill with none for the shorter lists
Test Code:
from collections import Counter
c = Counter({'b': 3, 'c': 2, 'a': 1})
import itertools as it
print([sorted(y for y in z if y is not None)
for z in it.izip_longest(*[[k] * l for k, l in c.items()])])
Results:
[['a', 'b', 'c'], ['b', 'c'], ['b']]
You can try this:
import itertools
the_dict = {'b': 3, 'c': 2, 'a': 1}
the_frequencies = [[a]*b for a, b in the_dict.items()]
the_list = itertools.izip_longest(the_frequencies)
the_final = map(list, list(itertools.izip_longest(*the_frequencies)))
print [[i for i in b if i != None] for b in the_final]
This solution uses itertools to zip the lists contained in the_frequencies that are created by multiplying a list of the key multiplied its corresponding value. izip then forms a list with the rows of the elements in the_frequencies, storing None if the count of the current iteration is greater than the length of any list in the list of lists.
From Python: create dict from list and auto-gen/increment the keys (list is the actual key values)?, it's possible to create a dict from a list using enumerate to generate tuples made up of incremental keys and elements in life, i.e.:
>>> x = ['a', 'b', 'c']
>>> list(enumerate(x))
[(0, 'a'), (1, 'b'), (2, 'c')]
>>> dict(enumerate(x))
{0: 'a', 1: 'b', 2: 'c'}
It is also possible to reverse the key-value by iterating through every key in the dict (assuming that there is a one-to-one mapping between key-value pairs:
>>> x = ['a', 'b', 'c']
>>> d = dict(enumerate(x))
>>> {v:k for k,v in d.items()}
{'a': 0, 'c': 2, 'b': 1}
Given the input list ['a', 'b', 'c'], how can achieve the dictionary where the elements as the key and incremental index as values without trying to loop an additional time to reverse the dictionary?
How about simply:
>>> x = ['a', 'b', 'c']
>>> {j:i for i,j in enumerate(x)}
{'a': 0, 'c': 2, 'b': 1}
I am trying to learn Python dictionary comprehension, and I think it is possible to do in one line what the following functions do. I wasn't able to make the n+1 as in the first or avoid using range() as in the second.
Is it possible to use a counter that automatically increments during the comprehension, as in test1()?
def test1():
l = ['a', 'b', 'c', 'd']
d = {}
n = 1
for i in l:
d[i] = n
n = n + 1
return d
def test2():
l = ['a', 'b', 'c', 'd']
d = {}
for n in range(len(l)):
d[l[n]] = n + 1
return d
It's quite simple using the enumerate function:
>>> L = ['a', 'b', 'c', 'd']
>>> {letter: i for i,letter in enumerate(L, start=1)}
{'a': 1, 'c': 3, 'b': 2, 'd': 4}
Note that, if you wanted the inverse mapping, i.e. mapping 1 to a, 2 to b etc, you could simply do:
>>> dict(enumerate(L, start=1))
{1: 'a', 2: 'b', 3: 'c', 4: 'd'}
This works
>>> l = ['a', 'b', 'c', 'd']
>>> { x:(y+1) for (x,y) in zip(l, range(len(l))) }
{'a': 1, 'c': 3, 'b': 2, 'd': 4}