【问题标题】:Dictionary creation from sorted list从排序列表创建字典
【发布时间】:2018-06-17 17:10:48
【问题描述】:

这个问题是关于嵌套字典理解的,在问这个问题之前我已经提到了 link1link2
我有一个列表,它的第一个元素是 None ,其余的是排序的正数列表。

sorted_ar = [None, 10, 10, 12, 12, 12, 15, 25] 

我的要求是将字典构建为:

key_dict = {10: [3, 2], 12: [12, 3], 15: [6, 1], 25: [7, 1]}

字典的值是一个双元素列表,第一个元素是key出现的索引的总和,第二个是出现的次数。
例如对于元素 12, 索引总和 = 3+4+5 = 12,出现次数为 3。
下面的代码做到了。

 key_dict = {k:[0,0] for k in sorted_ar if k!=None}
        for i in range(len(sorted_ar)):
            if sorted_ar[i]:
                key_dict[sorted_ar[i]][0] += i
                key_dict[sorted_ar[i]][1] += 1  

我的要求是使用字典理解来准备 key_dict 字典。

我的尝试:

key_dict = { 
    sorted_ar[i]:[ key_dict[sorted_ar[i]][0] + i,key_dict[sorted_ar[i]][0] + 1] 
    for i in range(1,len(sorted_ar)) if sorted_ar[i]!=None
}

但这给出了一些错误的结果,因为

key_dict = {10: [2, 1], 12: [5, 1], 15: [6, 1], 25: [7, 1]} 

在这种情况下我应该如何写字典理解?

【问题讨论】:

    标签: python python-3.x dictionary dictionary-comprehension


    【解决方案1】:

    如果您要使用排序,请查看itertools.groupby()enumerate() function 添加索引:

    from itertools import groupby
    
    filtered = ((i, v) for i, v in enumerate(sorted_ar) if v)
    grouped = ((v, list(g)) for v, g in groupby(filtered, lambda iv: iv[1]))
    result = {v: [sum(i for i, v in g), len(g)] for v, g in grouped}
    

    如果你愿意,你可以把这一切放在一个表达式中:

    result = {v: [sum(i for i, v in g), len(g)] for v, g in (
        (v, list(g)) for v, g in groupby((
            (i, v) for i, v in enumerate(sorted_ar) if v), lambda iv: iv[1]))}
    

    演示:

    >>> from itertools import groupby
    >>> sorted_ar = [None, 10, 10, 12, 12, 12, 15, 25]
    >>> filtered = ((i, v) for i, v in enumerate(sorted_ar) if v)
    >>> grouped = ((v, list(g)) for v, g in groupby(filtered, lambda iv: iv[1]))
    >>> {v: [sum(i for i, v in g), len(g)] for v, g in grouped}
    {10: [3, 2], 12: [12, 3], 15: [6, 1], 25: [7, 1]}
    

    或作为一个长表达式:

    >>> {v: [sum(i for i, v in g), len(g)] for v, g in ((v, list(g)) for v, g in groupby(((i, v) for i, v in enumerate(sorted_ar) if v), lambda iv: iv[1]))}
    {10: [3, 2], 12: [12, 3], 15: [6, 1], 25: [7, 1]}
    

    另一方面,您的字典方法不需要对输入进行排序,因此可以在 O(N) 时间内运行(排序需要 O(NlogN) 时间)。

    【讨论】:

      【解决方案2】:

      你可以试试这样的:

      sorted_ar = [None,10, 10, 12, 12, 12, 15, 25]
      
      track={}
      for i,j in enumerate(sorted_ar):
          if j not in track:
              track[j]=[(i,1)]
          else:
              track[j].append((i,1))
      
      
      final_={}
      for i,j in track.items():
          if i not in final_:
              final_[i]=(sum(list(map(lambda x:x[0],j))),sum(list(map(lambda x:x[1],j))))
      
      print(final_)
      

      输出:

      {None: (0, 1), 10: (3, 2), 15: (6, 1), 12: (12, 3), 25: (7, 1)}
      

      【讨论】:

        【解决方案3】:

        你可以试试这个:

        sorted_ar = [None, 10, 10, 12, 12, 12, 15, 25] 
        new_data = {i:[sum(c for c, b in enumerate(sorted_ar) if b == i), sorted_ar.count(i)] for i in sorted_ar if i}
        

        输出:

        {25: [7, 1], 10: [3, 2], 12: [12, 3], 15: [6, 1]}
        

        【讨论】:

        • 两种解决方案都是正确的,但是我尝试这种方式是有原因的。如果您查看有效的 for 循环代码(3rd sn-p),它看起来很简单/可读并且没有比较操作,值会在找到键时更新。我正在寻找这样一个没有可比性的解决方案,它是用类似于 for 循环解决方案的基本 python 编写的。
        【解决方案4】:

        好的,我找到了实现我的行为的方法,不知道为什么,但诀窍是字典更新需要在理解之外发生。

        def my_summer(i,num,key_dict):
            key_dict[num][0] = key_dict[num][0]+i
            return key_dict[num][0]  
        
        
        def my_counter(num,key_dict):
            key_dict[num][1] +=1
            return key_dict[num][1]
        
        sorted_ar = [None, 10, 10, 12, 12, 12, 15, 25] 
        key_dict = {k:[0,0] for k in sorted_ar if k!=None}
        
        key_dict = {sorted_ar[i]:[my_summer(i,sorted_ar[i],key_dict),my_counter(sorted_ar[i],key_dict)] for i in range(1,len(sorted_ar))}
        

        输出:{10: [3, 2], 12: [12, 3], 15: [6, 1], 25: [7, 1]}

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-08-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-12-17
          • 1970-01-01
          • 2015-05-22
          相关资源
          最近更新 更多