从Python中的频率字典构建列表列表



我需要帮助找到从频率字典构建频率排序列表的快捷方式。我可以通过将每个元素附加到列表,然后将每个列表附加到"列表列表"来构建列表列表(见下文)(仅频率1-3很容易),但如果我的频率高达100或更多,会发生什么?!必须有更好的方法。

dictionary = {'ab':2, 'bc':3, 'cd':1, 'de':1, 'ef':3, 'fg':1, 'gh':2}
list_1 = []
list_2 = []
list_3 = []
list_of_lists = []
for key, value in dictionary.items():
    if value == 1:
            list_1.append(key)
for key, value in dictionary.items():
    if value == 2:
            list_2.append(key)
for key, value in dictionary.items():
    if value == 3:
            list_3.append(key)
list_of_lists.append(list_1)
list_of_lists.append(list_2)
list_of_lists.append(list_3)
print list_of_lists

在Python中运行的副本如下:

[['de','cd','fg'],['ab','gh'],[[ef','bc']]

这正是我想要的,但它不适用于频率为100+的100000多个单词的语料库。请帮我找到一种更好、不那么乏味的方法来构建我的列表。


解决方案1-通过列表列表的反向映射(要求什么)

你正在寻找一个类似直方图的东西,但相反。

def inverseHistogram(valueFreqPairs):
    maxFreq = max(p[1] for p in valueFreqPairs)+1
    R = [[] for _ in range(maxFreq)]
    for value,freq in valueFreqPairs:
        R[freq] += [value]
    return R

演示:

>>> inverseHistogram(dictionary.items())
[[], ['de', 'cd', 'fg'], ['ab', 'gh'], ['ef', 'bc']]

解决方案2-通过defaultdict模式的反向映射(更干净)

如果你满足于使用字典来组织反向(看起来更优雅),那就更好了。这就是我个人的做法。

reverseDict = collections.defaultdict(list)
for value,freq in dictionary.items():
    reverseDict[freq].append(value)

演示:

>>> dict(reverseDict)
{1: ['de', 'cd', 'fg'], 2: ['ab', 'gh'], 3: ['ef', 'bc']}

旁注:例如,如果频率稀疏,例如,如果您的输入是{'onlyitem':999999999},则这也将为您节省空间,从而避免使列表大于内存,从而锁定您的机器

dict_of_lists = {}
for key, value in dictionary.items():
    if value in dict_of_lists:
        dict_of_lists[value].append(key)
    else:
        dict_of_lists[value] = [key]
list_of_lists = dict_of_lists.values()

您可以使用默认字典来存储数据:

import collections
dictionary={'ab':2, 'bc':3, 'cd':1, 'de':1, 'ef':3, 'fg':1, 'gh':2}
lists_by_frequency=collections.defaultdict(list)
for s, f in dictionary.iteritems():
        lists_by_frequency[f].append(s)
list_of_lists=[[] for i in xrange(max(lists_by_frequency)+1)]
for f, v in lists_by_frequency.iteritems():
        list_of_lists[f]=v
print lists_by_frequency
print list_of_lists

输出:

defaultdict(<type 'list'>, {1: ['de', 'cd', 'fg'], 2: ['ab', 'gh'], 3: ['ef', 'bc']})
[[], ['de', 'cd', 'fg'], ['ab', 'gh'], ['ef', 'bc']]

正如您所看到的,每个组都存储在其频率的索引中。如果频率至少是一,你可以从最终结果中减去一,这样你就不会在偏移量为零时得到一个空列表。

最佳方法:将它们全部放入dict

result = {}
for key, value in dictionary.iteritems():
  if not value in result:
    result[value] = []
  result[value].append(key)

稍微简单一点:

from collections import defaultdict
result = defaultdict(list)
for key, value in dictionary.iteritems():
  result[value].append(key)

或者创建列表:

result = [[]] * max(dictionary.values())
for key, value in dictionary.iteritems():
  result[value-1].append(key)

你可以做这样简单的事情:

dictionary = {'a1':2, ..., 'g':100}
MAX_FREQUENCE = max([dictionary[k] for k in dictionary]) //find the max frequency
list_of_lists=[[] for x in range(MAX_FREQUENCE] //generate empty list of lists
for k in dictionary:  
    dictionary[d[k]-1].append(k)

从list_of_lists开始的-1从0开始。动态列表的构造:[f(x) for x in iterable]被称为列表理解。

功能方式:

import collections
dictionary = {'ab':2, 'bc':3, 'cd':1, 'de':1, 'ef':3, 'fg':1, 'gh':2}
ldict = collections.defaultdict(list)
map(lambda (k, v): ldict[v].append(k), dictionary.iteritems())
list_of_lists = map(lambda x: ldict[x], xrange(0, max(ldict)+1))
print(list_of_lists)

此解决方案使用的方法与hochl的解决方案相同。它是功能性的:因此它更短,但通常需要更长的时间才能理解。:-)

注释:它太长了,因为IMHO dict/defaultdict构造函数(用于此用途)太有限。

最新更新