【问题标题】:Sorting 'End-to-End' like so: [[a,b][b,c][c,e]] [closed]像这样对“端到端”进行排序: [[a,b][b,c][c,e]] [关闭]
【发布时间】:2018-03-25 23:14:58
【问题描述】:

如何对这样的数组列表进行排序:

    ((green, yellow]),
    (red, orange),
    (blue, green),
    (yellow, red),
    (black, blue))

让两个元素首尾相连,如下所示:

    ((black, blue),
    (blue, green),
    (green, yellow),
    (yellow, red),
    (red, orange))

【问题讨论】:

  • 选择起点的规则是什么?你说“排序”,你的例子选择了排序顺序中第一个,所以……这就是你想要的吗?还是类似于最大化链条长度的起点? (如果是这样,如果三个起点都给出长度为 2 的链,但没有给出更长的链,会发生什么?任意选择?引发异常?)或者......我没有想到的东西?
  • 起始点是三元组[1] 的随机值,它没有匹配的父项。从这个起点开始: arr = (('ugly','green', 'yellow'), ('wolf','red', 'orange'), ('dog','blue', 'green'), ('mitten','yellow', 'red'), ('elf','black', 'blue')) ('sheep, 'silver', 'yellow') 我想创建所有可能的列表与孤独者“银色”或“黑色”。
  • 您的代码是否需要检测循环? (如果有,应该怎么做?)
  • 我想避免循环——每个项目只能出现一次。
  • “我想避免循环”是指“输入中不会有循环”,还是“如果有循环我们需要检测并引发 ValueError”,还是……?跨度>

标签: python arrays list sorting


【解决方案1】:

最容易理解的方法可能是将pair的元组转换为dict,然后从dict中读取结果:

>>> arr = (('green', 'yellow'),
...        ('red', 'orange'),
...        ('blue', 'green'),
...        ('yellow', 'red'),
...        ('black', 'blue'))
>>> dct = dict(arr)
>>> result = []
>>> key = min(dct)
>>> while key in dct:
...     result.append((key, dct[key]))
...     key = dct[key]
>>> print(result)
[('black', 'blue'), ('blue', 'green'), ('green', 'yellow'), ('yellow', 'red'), ('red', 'orange')]

一旦在一对中找到第二个值而不是另一对中对应的第一个值,这将立即结束,我认为这是您正在寻找的规则。但是,如果您的输入数据中可能存在循环,它将永远循环。为了解决这个问题,您可以保留一组迄今为止使用过的键,如果发现重复,则中断:

>>> seen = set()
>>> while key in dct:
...     if key in set: break
...     result.append((key, dct[key]))
...     seen.add(key)
...     key = dct[key]

min(dct) 按排序顺序选择第一个元素。如果你想选择不同的东西,你显然需要不同的东西。以下是一些示例:

successors = {succ for prev, succ in arr}

# Any arbitrary key that starts a chain
key = next(key for key in dct if key not in successors)

# Specifically a random key from among those that start a chain:
key = random.choice(dct.keys() - successors)

【讨论】:

  • 很好的解决方案,但您可能需要一种比min(dct) 更强大的方法来查找起始值:P
  • @Aran-Fey:为什么?这似乎是挑选出black 的规则。另外,如果规则类似于“选择使链长度最大化的值,如果有多个最大链则任意选择”,我认为 OP 不会将其称为“排序”。但我可能是错的。
  • 嗯,这就是我对问题的解释。但你可能是对的。我想,让我们拭目以待,看看 OP 是否对此感到满意。
  • 如果它们每个都包含三个元素,是否仍然可以将它们变成一个字典?例如: arr = (('ugly','green', 'yellow'), ('wolf','red', 'orange'), ('dog','blue', 'green'), ('手套','黄色', '红色'), ('小精灵','黑色', '蓝色'))
  • @NathanTurczan 这种情况下的规则是什么?我假设它类似于每个triplet[2] 指向下一个triplet[1],在这种情况下,您可以只创建一个字典{triplet[1]: triplet for triplet in arr},然后执行result.append(dct[key]) 和key = dct[key][2],或类似的。
【解决方案2】:

为了使它起作用,您需要假设只有两种独特的颜色,即不重复的颜色,因此它们无法链接。似乎所有元组都是唯一的,所以如果一种颜色出现两次,它首先出现一次,然后出现一次。因此,假设您知道要从哪个元组开始包含唯一元素,然后您可以循环并添加包含重复颜色的下一个元组。

tuples = [('green', 'yellow'),('red', 'orange'),('blue', 'green'),('yellow', 'red'),('black', 'blue')]

sorted_tuples = [tuples[4]]

def sort_tup(original_tup,sort_tup):
    for x in original_tup:
       if sort_tup[-1][1] == x[0]:
            return x

while len(sorted_tuples) < 5:
   sorted_tuples.append(sort_tup(tuples,sorted_tuples))

这个丑陋但没有更多结构的问题我认为这是解决它的一种相当简单的方法。

【讨论】:

  • 不喜欢这个解决方案。这具有二次运行时间复杂度,而您可以通过像 abarnert 的解决方案那样将元组存储在 dict 中轻松实现线性运行时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-27
  • 2011-06-13
  • 2020-12-25
  • 2018-03-28
相关资源
最近更新 更多