【问题标题】:Building a list of lists from a frequency dictionary in Python从 Python 中的频率字典构建列表列表
【发布时间】:2012-03-14 00:02:13
【问题描述】:

我需要帮助找到从频率字典中构建频率排序列表的快捷方式。我可以通过将每个元素附加到列表然后将每个列表附加到“列表列表”(只有频率 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+ 的 100,000+ 个单词的语料库。请帮助我找到一种更好、更简单的方式来构建我的列表。

【问题讨论】:

    标签: python list corpus


    【解决方案1】:

    解决方案 1 - 通过 list-of-lists 进行反向映射(要求的内容)

    您正在寻找类似于直方图的东西,但反过来。

    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},那么您就不必使列表大于您的内存,从而锁定您的机器。

    【讨论】:

    • 谢谢 ninjagecko,看来我也需要查看直方图!
    【解决方案2】:
    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()
    

    【讨论】:

    • 请记住,仅使用 dict.values() 不一定会以任何有意义的方式对结果进行排序。
    • 对。如果您想让它们排序:list_of_lists = map(lambda x: x[1], sorted(dict_of_lists.items())).
    • 由于我是编程新手,“地图”对我来说不是很清楚...我会做一些研究并尝试弄清楚...谢谢你,Rafal!
    • 是的,它不是一个很基础的语言元素,但是当你多写一点代码时mapfilterlambda等就很方便了。
    【解决方案3】:

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

    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']]
    

    如您所见,每个组都存储在其频率索引处。如果频率至少为 1,则您可能只需从最终结果中减去 1,这样您就不会在偏移量为零时得到一个空列表。

    【讨论】:

      【解决方案4】:

      最好的方法:把它们都扔到一个字典里

      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)
      

      【讨论】:

      • 如果频率值稀疏,以这种方式创建列表可能不是最优的。
      • 我认为 OP 想要这样......所有元素都存储在相应偏移量的列表。
      • 谢谢你,bluepnume。这里的第三个解决方案产生一个列表,这是我稍后需要的形式(将通过调用其索引来使用每个列表)。
      • 在此处无法将列表相乘。它不会创建 max(d.v()) 新列表,只会创建同一列表的 max(d.v()) 副本。 IOW,result 中的每个子列表都是一样的 -- 试试看。
      【解决方案5】:

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

      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)
      

      -1,因为 list_of_lists 从 0 开始。动态构建列表 :[f(x) for x in iterable] 称为 list comprehension

      【讨论】:

      • 如果频率超过 100,这会起作用吗?我不知道最大频率是多少。
      【解决方案6】:

      功能方式:

      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 解决方案相同的方法。它是功能性的:因此它更短 - 但通常需要更长的时间才能理解它。 :-)

      评论:这是“长”,因为恕我直言,dict / defaultdict 构造函数(对于此用途)太有限了。

      【讨论】:

        猜你喜欢
        • 2015-09-25
        • 2014-12-18
        • 1970-01-01
        • 2021-08-21
        • 1970-01-01
        • 2017-08-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多