简体   繁体   中英

python lists - convert an existing list of lists into a dict with multiple values per key using a comprehension

I have a relatively simple problem that is easily solved with setdefault , but I'm self-learning comprehensions right now and can't figure out how to do this with a comprehension.

Let's say I have a nested list where some of the inner lists have the same keys. This means that I should be able to generate a dict where some keys have multiple values. I keep trying to somehow append the values but every time it just returns that last single digit value or else give an error.

Here is an example:

>>> strlist
['hello w', 'hello', 'hello c', 'hello c c', 'dog']

>>> [[k,v] for k in set(sum([x.split() for x in strlist],[])) for v,x in enumerate(strlist) if k in x]
[['hello', 0], ['hello', 1], ['hello', 2], ['hello', 3], ['w', 0], ['c', 2], ['c', 3], ['dog', 4]]

I also tried it with a list of tuples, a tuple of tuples, a set of lists, a set of tuples, etc. Still can't get it to work with a comprehension.

Here are a few failed attempts:

>>> dict([(k,v) for k in set(sum([x.split() for x in strlist],[])) for v,x in enumerate(strlist) if k in x])
{'hello': 3, 'w': 0, 'c': 3, 'dog': 4}

>>> {k:k[v] for k,v in [[k,v] for k in set(sum([x.split() for x in strlist],[])) for v,x in enumerate(strlist) if k in x]}
Traceback (most recent call last):
  File "<pyshell#285>", line 1, in <module>
    {k:k[v] for k,v in [[k,v] for k in set(sum([x.split() for x in strlist],[])) for v,x in enumerate(strlist) if k in x]}
  File "<pyshell#285>", line 1, in <dictcomp>
    {k:k[v] for k,v in [[k,v] for k in set(sum([x.split() for x in strlist],[])) for v,x in enumerate(strlist) if k in x]}
IndexError: string index out of range

>>> {k:{v} for k,v in [[k,v] for k in set(sum([x.split() for x in strlist],[])) for v,x in enumerate(strlist) if k in x]}
{'hello': {3}, 'w': {0}, 'c': {3}, 'dog': {4}}

The goal is to get this:

>>> {'hello': {0, 1, 2, 3], 'w': {0}, 'c': {2, 3}, 'dog': {4}}

Is this even possible with a comprehension or must I use one of the more common traditional loop methods?

Use your method to transform strlist to list of lists and then you can use collections.defaultdict :

from collections import defaultdict

lst = [
    ["hello", 0],
    ["hello", 1],
    ["hello", 2],
    ["hello", 3],
    ["w", 0],
    ["c", 2],
    ["c", 3],
    ["dog", 4],
]   

d = defaultdict(set)
for x, y in lst:
    d[x].add(y)
    
print(d)
# defaultdict(<class 'set'>, {'hello': {0, 1, 2, 3}, 'w': {0}, 'c': {2, 3}, 'dog': {4}})

Since, you ask for a dictionary-comprehension:

d = {k: set(y for x, y in lst if x == k) for k, _ in lst}

This is a way of doing it in one line, using dict comprehension. However, I'm not sure if this is a best option in terms of efficiency than a more conventional for loop, using things like setdefault() and some temporal list.

list_ = ['hello w', 'hello', 'hello c', 'hello c c', 'dog']
result = {
    word: {i for i, phrase in enumerate(list_) if word in phrase}
    for string in list_
    for word in string.split()
}

content of result :

{'hello': {0, 1, 2, 3}, 'w': {0}, 'c': {2, 3}, 'dog': {4}}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM