【问题标题】:Remove tuples from dictionary value list if first value in tuple = 1如果元组中的第一个值 = 1,则从字典值列表中删除元组
【发布时间】:2017-07-10 07:34:27
【问题描述】:

首先我有一个字典 d1,看起来像这样:

d1 = {    'w' : ['a', 'a', 'a', 'a', 'a', 'b', 'b', 'b', 'c', 'c'],
          'x' : ['d', 'd', 'd', 'e', 'e'],
          'y' : ['f', 'f', 'g'],
          'z' : ['h', 'i']    
     }

然后我遍历该字典并创建一个新字典,其中每个值都是一个包含两个元素的列表:整数和列表。整数是 d1 中该值中的字符串数。该列表包含元组,每个元组包含来自 d1 的字符串(在元组的位置 1)和该字符串在 d1 中出现的次数(在元组的位置 0):

d2 = {   'w' : [10, [(5, 'a'), (3, 'b'), (2, 'c')], 
         'x' : [5, [(3, 'd'), (2, 'e')],
         'y' : [3, [(2, 'f'), (1, 'g')],
         'z' : [2, [(1, 'h'), (1, 'i')]    
     }

我想删除任何只出现一次的字符串('g'、'h'和'i'),所以最后我想要:

dFinal = {    'w' : [10, [(5, 'a'), (3, 'b'), (2, 'c')],
              'x' : [5, [(3, 'd'), (2, 'e')],
              'y' : [2, [(2, 'f')]    
         }

我阅读了一个我认为是字典理解的示例,如果值列表的长度小于 2,则删除整个字典项:

d = {k:v for k,v in d.items() if len(v) > 1}

我正在尝试掌握列表/字典的理解,并希望使用类似的东西来实现我所描述的内容,并在此过程中学到一些东西。

起初我尝试编写一个以 d2 作为参数的函数,但我不知道如何引用每个元组的位置 0。

然后认为使用没有元组的 d1 制作 dFinal 可能会容易得多,而不是尝试更改 d2。

如果您能描述一种从 d1 和/或 d2 生成 dFinal 的简洁方法,并解释其思考过程,我将不胜感激。两者都将真正帮助我理解如何使用推导式精确操作字典列表。

谢谢!

【问题讨论】:

    标签: python python-2.7 dictionary list-comprehension dictionary-comprehension


    【解决方案1】:

    好吧,您可以使用Counter 对象。老实说,我会使用循环,因为它可能会更有效。

    In [1]: from collections import Counter
    

    编辑:以下是我实际执行此操作的方法,没有理解:

    In [17]: for k,v in d1.items():
        ...:     counts = Counter(v)
        ...:     counts = [t for t in counts.items() if t[1] > 1]
        ...:     if len(counts) > 0:
        ...:         dfinal[k] = [sum(c[1] for c in  counts), counts]
        ...:
    
    In [18]: dfinal
    Out[18]:
    {'w': [10, [('b', 3), ('a', 5), ('c', 2)]],
     'x': [5, [('d', 3), ('e', 2)]],
     'y': [2, [('f', 2)]]}
    

    【讨论】:

    • 非常感谢。但是,这不会调整每个值开头的“总和整数”。 10、5 和 3 需要变为 10、5 和 2。
    • @ddrsee 错过了这一点。轻松修复。
    • 谢谢一百万。我将阅读 Counter 并尝试弄清楚这里发生了什么......
    • 这不会保留列表顺序,尽管如果这很重要,那么排序应该很简单。
    • @ddrsee 只需使用counts = [t for t in counts.most_common() if t[1] > 1]
    【解决方案2】:

    我认为这不是很好的风格,但你可以这样做:

    dFinal = {k: [sum([i for i, c in v[1] if i != 1]),
                  [(i, c) for i, c in v[1] if i != 1]]
              for k, v in d2.items()
              if [(i, c) for i, c in v[1] if i != 1]}
    

    编辑:现在更新计数。同样,如果理解看起来像这样,是时候重构了。

    【讨论】:

    • 这不会调整成员数量'y': [3, [(2, 'f')]] 尽管实际上,它们可能没有必要。
    • 他们是必要的! :-)
    • 非常感谢。您有最喜欢的关于此类推导式(以及重构是什么)的教程吗?
    • @ddrsee 他们可以,但请注意,在这种情况下,您在理解中使用了[(i, c) for i, c in v[1] if i != 1] 三次。由于您不能像在循环中那样将其存储为中间值,因此创建了三个单独的列表!但是你只需要创建一次,真的,如果你考虑一下的话。此外,像这样的理解完全杀死可读性,这真的不值得为了一点点速度增益而牺牲。
    • @juanpa.arrivillaga 正确地解释了为什么编写如此复杂的推导式不是一个好主意。代码的阅读频率通常比编写的频率高。从现在起六个月后,我不会一眼看懂代码,而且它的效率也低于预期。
    【解决方案3】:

    另一种选择:速度较慢但更容易理解:

    def has_dupe(lst):
        return any([x[0] > 1 for x in lst[1]])
    
    def reduce_list(lst):
        result = [(x, y) for (x, y) in lst[1] if x > 1]
        return [sum([x for (x, y) in result]), result]
    
    d = {key: reduce_list(value) for key, value in d2.items() if has_dupe(value)}
    

    【讨论】:

      【解决方案4】:

      这个

      from collections import Counter
      
      d2 = {k: [len(v), sorted(Counter(v).items())] for k, v in d1.items()}
      
      dFinal = {k: [v1, [(y, x) for x, y in v2 if y > 1]] for k, (v1, v2) in d2.items()}
      

      我的d2dFinal 与您的略有不同。这是我的d2

      {'w': [10, [('a', 5), ('b', 3), ('c', 2)]],
       'x': [5, [('d', 3), ('e', 2)]],
       'y': [3, [('f', 2), ('g', 1)]],
       'z': [2, [('h', 1), ('i', 1)]]}
      

      这是我的dFinal

      {'w': [10, [(5, 'a'), (3, 'b'), (2, 'c')]],
       'x': [5, [(3, 'd'), (2, 'e')]],
       'y': [3, [(2, 'f')]],
       'z': [2, []]}
      

      但您可以自己轻松解决。

      顺便说一句:我会使用函数来使字典和列表推导看起来更容易。现在它是不可读的。

      【讨论】:

      • ['a', 'a', 'a', 'a', 'a', 'b', 'b', 'b', 'c', 'c'] 转换为[('a', 5), ('b', 3), ('c', 2)]
      • 您不需要将Counter 对象转换为dict 对象来执行此操作。只需删除对dict 的调用,您就会发现它的工作原理完全相同。
      • 是的,我更新了它。你说的对。我正在玩一个小终端,所以我错过了:-)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-23
      • 2021-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-26
      相关资源
      最近更新 更多