【问题标题】:how to print dictionary key in the even frequency order如何以偶数频率顺序打印字典键
【发布时间】:2019-04-01 19:12:15
【问题描述】:

我想打印出偶数频率的字典键、值对

a = dict('A': 3, 'B': 5} => ['A', 'B', 'A', 'B', 'A', 'B', 'B', 'B']

a = dict('A': 4, 'B': 1} => ['A', 'B', 'A', 'A', 'A']

我知道我可以使用 while 循环来打印每个键并每次删除计数,直到所有键的所有值都为 0,但如果有更好的方法吗?

    def func(d: dict):
        res = []
        while any(i > 0 for i in d.values()):
            for k, c in d.items():
                if c > 0:
                    res.append(k)
                    d[k] -= 1
        return res

【问题讨论】:

  • 请显示您当前的尝试。您使用的 Python 版本是否 >= 3.6?
  • 当然,更新了问题

标签: python python-3.x


【解决方案1】:

(我假设您使用的 Python 版本可以保证字典的迭代顺序)

这是一个 itertools-y 方法。它为每个字母创建一个生成器,生成给定次数的字母,并将所有这些字母与zip_longest 组合在一起,以便它们均匀地生成。

from itertools import repeat, zip_longest

def iterate_evenly(d):
    generators = [repeat(k, v) for k,v in d.items()]
    exhausted = object()
    for round in zip_longest(*generators, fillvalue=exhausted):
        for x in round:
            if x is not exhausted:
                yield x


print(list(iterate_evenly({"A": 3, "B": 5})))
print(list(iterate_evenly({"A": 4, "B": 1})))

结果:

['A', 'B', 'A', 'B', 'A', 'B', 'B', 'B']
['A', 'B', 'A', 'A', 'A']

你可以用更少的行做同样的事情,虽然它变得更难阅读。

from itertools import repeat, zip_longest

def iterate_evenly(d):
    exhausted = object()
    return [x for round in zip_longest(*(repeat(k, v) for k,v in d.items()), fillvalue=exhausted) for x in round if x is not exhausted]

print(iterate_evenly({"A": 3, "B": 5}))
print(iterate_evenly({"A": 4, "B": 1}))

【讨论】:

    【解决方案2】:

    对于单线。

    首先,创建一个包含两个元素的列表:As 列表和Bs 列表:

    >>> d = {'A': 3, 'B': 5}
    >>> [[k]*v for k, v in d.items()]
    [['A', 'A', 'A'], ['B', 'B', 'B', 'B', 'B']]
    

    [k]*v 表示:带有v ks 的列表。其次,交错As 和B。我们需要zip_longest,因为zip 会在第一个列表结束后停止:

    >>> import itertools
    >>> list(itertools.zip_longest(*[[k]*v for k, v in d.items()]))
    [('A', 'B'), ('A', 'B'), ('A', 'B'), (None, 'B'), (None, 'B')]
    

    现在,只需展平列表并删除 None 值:

    >>> [v for vs in itertools.zip_longest(*[[k]*v for k, v in d.items()]) for v in vs if v is not None]
    ['A', 'B', 'A', 'B', 'A', 'B', 'B', 'B']
    

    其他例子:

    >>> d = {'A': 4, 'B': 1}
    >>> [v for vs in itertools.zip_longest(*[[k]*v for k, v in d.items()]) for v in vs if v is not None]
    ['A', 'B', 'A', 'A', 'A']
    

    【讨论】:

      【解决方案3】:

      您可以将sum 与生成器理解一起使用:

      res = sum(([key]*value for key, value in d.items()), [])
      

      这利用了sum 可以“添加”任何可以使用+ 运算符的事实,例如列表,以及序列乘法 ("A"*4 == "AAAA")。

      如果您希望顺序随机化,请使用random 模块:

      from random import shuffle
      shuffle(res)
      

      如 Thierry Lathuille 所说,如果您想按原始顺序循环遍历值,您可以使用一些 itertools 魔法:

      from itertools import chain, zip_longest
      res = [*filter(
          bool,  # drop Nones
          chain(*zip_longest(
              *([key]*val for key, val in d.items()))
          )
      )]
      

      【讨论】:

      • 虽然问题中没有明确说明,但我认为 OP 希望按照原始字典中给出的顺序循环遍历这些值。
      【解决方案4】:

      作为复制 & zip_longest 方法的替代方案,让我们尝试简化 OP 的原始代码:

      def function(dictionary):
          result = []
      
          while dictionary:
              result.extend(dictionary)
              dictionary = {k: v - 1 for k, v in dictionary.items() if v > 1}
      
          return result
      
      print(function({'A': 3, 'B': 5}))
      print(function({'A': 4, 'B': 1}))
      

      输出

      % python3 test.py
      ['A', 'B', 'A', 'B', 'A', 'B', 'B', 'B']
      ['A', 'B', 'A', 'A', 'A']
      %
      

      虽然看起来可能不一样,但它不会对字典参数造成破坏,这与 OP 的原始代码不同。

      【讨论】:

      • 这是明智之举
      【解决方案5】:

      也可以使用通过扩展每个字典条目形成的一种(位置,字符)元组来完成:

      a = {'A': 3, 'B': 5}
      result = [c for _,c in sorted( (p,c) for c,n in a.items() for p,c in enumerate(c*n))]
      print(result) # ['A', 'B', 'A', 'B', 'A', 'B', 'B', 'B']
      

      如果字典的顺序是可用的,你可以放弃排序并使用这个:

      result = [c for i in range(max(a.values())) for c,n in a.items() if i<n]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-20
        • 1970-01-01
        相关资源
        最近更新 更多