Append to a dict of lists with a dict comprehension

前端 未结 4 1241
你的背包
你的背包 2021-02-20 05:20

Suppose I have a large list of words. For an example:

>>> with open(\'/usr/share/dict/words\') as f:
...     words=[word for word in f.read().split(\'\\         


        
相关标签:
4条回答
  • 2021-02-20 06:05

    No - dict comprehensions are designed to generate non-overlapping keys with each iteration; they don't support aggregation. For this particular use case, a loop is the proper way to accomplish the task efficiently (in linear time).

    0 讨论(0)
  • 2021-02-20 06:06

    This is not exactly a dict comprehension, but:

    reduce(lambda d, w: d.setdefault(w[0], []).append(w[1]) or d,
           ((w[0].lower(), w) for w in words
            if w[0].lower() in 'aeiou'), {})
    
    0 讨论(0)
  • 2021-02-20 06:09

    I'd use filter:

    >>> words = ['abcd', 'abdef', 'eft', 'egg', 'uck', 'ice']
    >>> index = {k.lower() : list(filter(lambda x:x[0].lower() == k.lower(),words)) for k in 'aeiou'}
    >>> index
    {'a': ['abcd', 'abdef'], 'i': ['ice'], 'e': ['eft', 'egg'], 'u': ['uck'], 'o': []}
    
    0 讨论(0)
  • 2021-02-20 06:11

    It is not possible (at least easily or directly) with a dict comprehension.

    It is possible, but potentially abusive of the syntax, with a set or list comprehension:

    # your code:    
    d={}
    for word in words:
       if word[0].lower() in 'aeiou':
           d.setdefault(word[0].lower(),[]).append(word)        
    
    # a side effect set comprehension:  
    index={}   
    r={index.setdefault(word[0].lower(),[]).append(word) for word in words 
            if word[0].lower() in 'aeiou'}     
    
    print r
    print [(k, len(d[k])) for k in sorted(d.keys())]  
    print [(k, len(index[k])) for k in sorted(index.keys())]
    

    Prints:

    set([None])
    [('a', 17094), ('e', 8734), ('i', 8797), ('o', 7847), ('u', 16385)]
    [('a', 17094), ('e', 8734), ('i', 8797), ('o', 7847), ('u', 16385)]
    

    The set comprehension produces a set with the results of the setdefault() method after iterating over the words list. The sum total of set([None]) in this case. It also produces your desired side effect of producing your dict of lists.

    It is not as readable (IMHO) as the straight looping construct and should be avoided (IMHO). It is no shorter and probably not materially faster. This is more interesting trivia about Python than useful -- IMHO... Maybe to win a bet?

    0 讨论(0)
提交回复
热议问题