【问题标题】:How to display a circular list from a calculated index如何从计算的索引中显示循环列表
【发布时间】:2014-05-12 10:39:33
【问题描述】:

我有一个类似的字典列表

d = [{10: "a"}, {20: "b"}, {30: "c"}]

此列表按键排序。我不依附于格式或数据类型 - 无论如何我都是从外部来源构建此列表(也就是说,如果有帮助,可以更改它)

我还有一个变量 x,范围从 0100

我想要得到的是列表d 重新排列(或重建,或复制到其他地方),从大于x 的第一个键开始。例如(编辑,对不起,我在最初的例子中犯了一个错误)

  • 如果x == 2 那么d = [{10: "a"}, {20: "b"}, {30: "c"}]
  • 如果x == 12 那么d = [{20: "b"}, {30: "c"}, {10: "a"}]
  • 如果x == 22 那么d = [{30: "c"}, {10: "a"}, {20: "b"}]
  • 如果x == 32 那么d = [{10: "a"}, {20: "b"}, {30: "c"}]

我称它为“圆形”,因为它以封闭的方式表示“带有key > x 的下一个len(d) 元素”。

我将以链式if 的形式执行此操作,每次手动构建列表(上面的示例涵盖了案例)。除了是一个糟糕的解决方案之外,如果 len(d) 变大(现在是 3 所以最坏的情况我会选择链式 if),它就不能完全扩展。

解决这个问题的pythonic解决方案是什么?

【问题讨论】:

  • 所有字典都有一个键吗?您是否考虑过使用OrderedDict 或元组列表?
  • 是的,它们确实有一个唯一的密钥。我没有考虑OrderedDict 或元组列表,但我可以将数据类型更改为除我的ifs 之外的任何方便的解决方案。
  • 字典中的所有键都是唯一的,事实上只有一个让我感到惊讶。确定最佳数据结构需要更多信息。您的示例与描述不匹配“从大于x 的第一个键开始”
  • 我的意思是每个字典都有一个键,所有这些键都是唯一的(它们是时间戳)。因此没有像[{10: "a"}, {10: "b"}] 这样的案例。我从测量中得到的实际上是我提到的列表。
  • 啊——你是对的,我刚刚意识到我在示例中犯了一个错误。我会马上改正的。

标签: python list circular-buffer


【解决方案1】:

没有特别的原因,我想使用一个列表理解来解决这个问题。这是我想出的:

>>> from itertools import product
>>> d = [{10: "a"}, {20: "b"}, {30: "c"}]
>>> for x in (2, 12, 22, 32):
...     [e for i, e in product(range(2), d) 
...      if (0, x) < (i, next(iter(e))) <= (1, x)]
...
[{10: 'a'}, {20: 'b'}, {30: 'c'}]
[{20: 'b'}, {30: 'c'}, {10: 'a'}]
[{30: 'c'}, {10: 'a'}, {20: 'b'}]
[{10: 'a'}, {20: 'b'}, {30: 'c'}]

【讨论】:

    【解决方案2】:

    当 x 为 22 时,这首先给出 30,因为 30 是第一个键 > 22:

    d  = [{10: "a"}, {20: "b"}, {30: "c"}]
    dd = d * 2 
    
    for x in [2, 12, 22, 32, 42]:
        for i, h in enumerate(dd):
            k, v = h.items()[0]
            if k > x or i >= len(d): break
        print x, dd[i:i+len(d)]
    

    输出:

    2 [{10: 'a'}, {20: 'b'}, {30: 'c'}]
    12 [{20: 'b'}, {30: 'c'}, {10: 'a'}]
    22 [{30: 'c'}, {10: 'a'}, {20: 'b'}]
    32 [{10: 'a'}, {20: 'b'}, {30: 'c'}]
    42 [{10: 'a'}, {20: 'b'}, {30: 'c'}]
    

    但由于列表已排序,因此您可以进行二分搜索以提高性能。

    【讨论】:

    • 谢谢 - 我意识到(也感谢 jonrsharpe 的评论)我在示例中犯了一个错误
    【解决方案3】:

    您可以使用以下内容,但这适用于简单的数据格式/类型。如果您的输入更复杂,那么您可能需要稍微调整一下。

    d = [y for y in d if list(y)[0] > x] + [y for y in d if list(y)[0] <= x]
    

    【讨论】:

      【解决方案4】:

      我会使用切片和enumerate:

      for index, subdict in enumerate(d):
          if list(subdict)[0] > x:
              d = d[index:] + d[:index]
              break
      

      是否有更好的数据结构满足您的需求?可能,但如果没有更多信息,很难确定它会是什么。正如您所说,所有子词典中的键在列表中都是唯一的,您应该查看collections.OrderedDict - 您可以将所有数据放在同一个结构中。

      【讨论】:

        猜你喜欢
        • 2020-11-18
        • 2019-01-27
        • 2011-06-11
        • 1970-01-01
        • 2020-01-06
        • 1970-01-01
        • 2020-10-18
        • 1970-01-01
        相关资源
        最近更新 更多