简体   繁体   中英

How to create a list of values in a dictionary comprehension in Python

Taking a very simple example of looping over a sentence and creating a dictionary which maps {x:y} , where x is a key representing the length of the words and y is a list of words in the sentence that contain x amount of letters

Input:

mywords = "May your coffee be strong and your Monday be short"

Expected Output:

{2: ['be', 'be'], 3: ['May', 'and'], 4: ['your', 'your'], 5: ['short'], 6: ['coffee', 'strong', 'Monday']}

Here's an attempt that creates a list of values but overwrites it each time:

{len(x):[x] for x in mywords.split()}
{2: ['be'], 3: ['and'], 4: ['your'], 5: ['short'], 6: ['Monday']}

Is it possible to do this in one line in Python?

Sure, you can, using sorted + groupby , but it doesn't look great.

from itertools import groupby
d = dict([(k, list(g)) for k, g in groupby(sorted(mywords.split(), key=len), key=len)])

print(d)
{2: ['be', 'be'],
 3: ['May', 'and'],
 4: ['your', 'your'],
 5: ['short'],
 6: ['coffee', 'strong', 'Monday']}

PS, Here's my answer (using defaultdict that I recommend over this) to the original question .

Don't try to cram everything in one line, it won't be readable. This is a simple, easy-to-understand solution, even if it takes a couple of lines:

from collections import defaultdict

mywords = "May your coffee be strong and your Monday be short"    
ans = defaultdict(list)

for word in mywords.split():
    ans[len(word)].append(word)

It is possible to use a regular expression by build a raw string from 1 to the max length of the word then use the groups and iterate their position as a the size of the word. Lastly using a defaultdict as set add the words from the group to the dictionary.

text = "May your hot chocolate be delicious and sweet and your Monday be short"

max_len=0
for word in text.split():
    if len(word)>max_len: 
        max_len=len(word) 

pattern=[]

for index in range(1,max_len+1):
    index=str(index)
    pattern.append(r"(\b\w{"+"{index}".format(index=index)+r"}\b\s+)*")

pattern=''.join(pattern)
print(pattern)
groups=re.findall(pattern,text)
dict = defaultdict(set)
for group in groups:
    for position,value in enumerate(group):
        if len(value)>0:
             dict[position+1].add(value)

 print(dict)

output:

 defaultdict(<class 'set'>, {3: {'May ', 'hot ', 'and '}, 4: {'your '}, 9: {'delicious ', 'chocolate '}, 2: {'be '}, 5: {'sweet '}, 6: {'Monday '}})

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