我需要帮助找到从频率字典构建频率排序列表的快捷方式。我可以通过将每个元素附加到列表,然后将每个列表附加到"列表列表"来构建列表列表(见下文)(仅频率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构造函数(用于此用途)太有限。