如何生成元组相关记录的列表

时间:2013-07-07 15:57:25

标签: python list tuples

我需要从元组列表中生成一个列表:

a = [(1,2), (1,3), (2,3), (2,5), (2,6), (3,4), (3,6), (4,7), (5 6), (5,9), (5,10), (6,7)
             (6.10) (6.11) (7.8) (7.12) (8.12) (9.10) (10.11)]

规则是: - 我有任何记录(begin = random.choice (a)) - 新列表中的项目必须具有以下关系:      列表中每个元组的最后一项必须等于要插入的下一个元组的第一项。

有效输出的示例(从元组(3.1)开始):

[(3, 1), (1, 2), (2, 3), (3, 4), (4, 7), (7, 8), (8, 12), (12, 7), (7, 6), (6, 2), (2, 5), (5, 6), (6, 10), (10, 5) (5, 9), (9, 10), (10, 11), (11, 6), (6, 3)]

我该怎么做?它使用列表理解吗? 谢谢!

4 个答案:

答案 0 :(得分:0)

在这里,lisb将按照您寻找的顺序填充元组。当然,如果lisa提供了适当的元组(即,每个元组具有与另一个元组的第0个值匹配的第1个值)。无论实现如何,您的样本列表都不起作用,因为所有值都不匹配(例如,没有第12个元素,因此元组不能连接到任何其他元组)...所以你应该想出一个更好的样本列表。

经过测试,正常工作。

import random

lisa = [(1, 2), (3, 4), (2, 3), (4, 0), (0, 9), (9, 1)]
lisb = []

current = random.choice(lisa)

while True:
    lisa.remove(current)
    lisb.append(current)
    current = next((y for y in lisa if y[0] == current[1]), None)
    if current == None:
        break

print lisb

如果您不想从lisa删除项目,只需切片新列表。

答案 1 :(得分:0)

作为生成器功能:

def chained_tuples(x):
    oldlist = x[::]
    item = random.choice(oldlist)
    oldlist.remove(item)
    yield item

    while oldlist:
        item = next(next_item for next_item in oldlist if next_item[0] == item[1])
        oldlist.remove(item)
        yield item

如上所述,如果您的列表实际上并不是可链接的,那么您将得到一个不完整的回复,例如您的示例列表。

答案 2 :(得分:0)

我认为到目前为止所有答案都缺少要求(至少根据您的示例输出)找到最长链。

我建议的解决方案是递归解析所有可能构造的链,并返回最长的结果。该函数如下所示:

def generateTuples(list, offset, value = None):
  if value == None: value = list[offset]
  list = list[:offset]+list[offset+1:]
  res = []
  for i,(a,b) in enumerate(list):
    if value[1] in (a,b):
      if value[1] == a:  
        subres = generateTuples(list, i, (a,b))
      else:
        subres = generateTuples(list, i, (b,a))
      if len(subres) > len(res):
        res = subres
  return [value] + res

你会这样称呼它:

results = generateTuples(a, 1, (3,1))

制作清单:

[(3, 1), (1, 2), (2, 3), (3, 4), (4, 7), (7, 8), (8, 12), (12, 7), (7, 6),
 (6, 2), (2, 5), (5, 6), (6, 10), (10, 5), (5, 9), (9, 10), (10, 11),
 (11, 6), (6, 3)]

该函数的第一个参数是元组的源列表,第二个参数是要使用的第一个元素的偏移量,第三个参数是可选的,但允许您覆盖第一个元素的值。当您想要以与您的示例中相反的顺序开始使用元组时,后者非常有用。

答案 3 :(得分:0)

只是添加解决此问题的另一种方法:

import random
from collections import defaultdict

lisa = [(1, 2), (3, 4), (2, 3), (4, 0), (0, 9), (9, 1)]

current_start, current_end = lisa[random.randint(0, len(lisa) - 1)]
starts = defaultdict(list)
lisb = [(current_start, current_end)]

for start, end in lisa:
    starts[start].append(end)

while True:
    if not starts[current_end]:
        break
    current_start, current_end = current_end, starts[current_end].pop()
    lisb.append((current_start, current_end))

注意:您必须确保lisa不为空。