【问题标题】:Python: Determine whether list of lists contains a defined sequencePython:确定列表列表是否包含定义的序列
【发布时间】:2014-08-23 03:10:21
【问题描述】:

我有一个子列表列表,我想查看第一个子列表中的任何整数值加一个是否包含在第二个子列表中。对于所有这些值,我想查看该值加一是否包含在第三个子列表中,依此类推,以这种方式在所有子列表中进行。如果有办法以这种方式从第一个子列表到最后一个子列表,我希望返回 True;否则我希望返回 False。对于第一个子列表中的每个值,我想看看是否可以在从左到右读取的每个子列表中找到该值加上 n,其中 n 是该子列表在较大列表中的索引值..(抱歉措辞笨拙- -我不确定如何在不使用更多单词的情况下清理我的语言。)

编辑:(所需输出的先前表述不明确。)对于第一个子列表中的每个值,我想看看是否可以在从左到右读取的每个子列表中找到该值加上 n,其中 n 是索引值较大列表中的子列表。

这是我写的。

a = [ [1,3],[2,4],[3,5],[6],[7] ]

def find_list_traversing_walk(l):

    for i in l[0]:

        index_position = 0
        first_pass = 1
        walking_current_path = 1

        while walking_current_path == 1:

            if first_pass == 1:
                first_pass = 0
                walking_value = i

            if walking_value+1 in l[index_position + 1]:

                index_position += 1
                walking_value  += 1

                if index_position+1 == len(l):
                    print "There is a walk across the sublists for initial value ", walking_value - index_position
                    return True

            else:
                walking_current_path = 0

    return False

print find_list_traversing_walk(a)

我的问题是:我是否在这里忽略了一些简单的事情,或者这个函数会为所有真阳性返回 True,而对于所有真阴性返回 False?是否有更简单的方法来完成预期任务?如果其他人可以提供任何反馈,我将不胜感激!

【问题讨论】:

  • 在你的例子中,find_list_traversing_walk(a) 会返回 False 吗?
  • 我的示例应该评估为 True。我想我在对@alfasin 的回答的评论中更接近于更好的语言:对于第一个子列表中的每个值,我想看看是否可以在从左到右阅读的每个子列表中找到该值加上 n,其中 n 是索引值较大列表中的该子列表。这有意义吗?
  • 每个子列表中的项目数量是否受到限制,或者子列表可以包含三个或四个或任意数量的项目?
  • 理论上,一个子列表中可能有任何有限数量的值,尽管任何子列表包含三个以上的值的可能性极小。看看下面@Warren 的回答——真是天才。
  • 是的,当我读到它时,我赞成它。

标签: python algorithm function loops


【解决方案1】:

您可以将所需的操作视为对一系列集合的归约,其中归约操作是以下函数:

In [25]: def func(x, y):
   ....:     return set([t+1 for t in x]) & set(y)
   ....:

也就是说,func 接受两个集合,将第一个集合中的每个元素加 1,并返回该集合与第二个集合的交集。在a 中按顺序应用此函数。如果最终结果不是空集,则答案为 True:

In [29]: a = [ [1,3],[2,4],[3,5],[6],[7] ]

In [30]: bool(reduce(func, a))
Out[30]: True

In [31]: b = [ [1],[2,4],[5] ]

In [32]: bool(reduce(func, b))
Out[32]: False

bool 将非空集转换为 True,将空集转换为 False。)

请注意,如果输入通常是一个很长的序列,并且您希望在几个步骤内知道答案为 False,那么这不是一个非常有效的解决方案,因为它总是遍历整个输入。

【讨论】:

  • 哇,感谢您指出 'reduce' 功能——这非常简洁!
  • 我接受了这个答案,因为它很优雅,而且你帮助我完成了它。
  • "... func() 怎么知道..."func() 不知道;是 reduce 使用适当的参数调用 func()reduce(实际上)计算 func(...(func(func(a[0], a[1]), a[2])...), a[n-1])。用中缀表示法更容易表达。即假设归约操作为加法,输入序列为a = [1, 3, 5, 2, 4]。然后减少是((((1 + 3) + 5) + 2) + 4)。像这样的缩减是fold 的一个示例:en.wikipedia.org/wiki/Fold_%28higher-order_function%29
  • 非常感谢,@Warren!非常感谢您的详尽解释和链接。
【解决方案2】:

有没有更简单的方法来完成预期的任务?

是的,定义递归解决方案会更容易:

def find(lst, index):
    if index == len(lst)-1:
        return True
    for i in lst[index]:
        if i+1 in lst[index+1]:
            return find(lst, index+1)
    else:
        return False             

a = [ [1,3],[2,4],[3,5],[6],[7] ]
print find(a, 0) # prints "True"

a = [ [1,3],[2,4],[3,5],[6],[7], [9] ]
print find(a, 0) # prints "False"

更新
您在评论中描述的内容有点复杂(next+1 需要成为以前使用过的“人”之一) - 但并不多:

def find(lst, part_res, index):
    if index == len(lst)-1:
        return True

    found = False
    new_part_res = []
    for i in part_res:
        if i+1 in lst[index+1]:
            found = True
            new_part_res.append(i+1)

    if not found:
        return False
    else:
        return find(lst, new_part_res, index+1)


a = [ [1,3],[2,4],[3,5],[6],[7] ] 
print find(a, a[0], 0) # True

a = [ [1],[2,4],[5] ]
print find(a, a[0], 0) # False

【讨论】:

  • 啊,有趣的想法,但 a = [ [1],[2,4],[5] ] 产生 True 但我希望它返回 False,因为 1+1=2 [到目前为止还不错],但 2+1 !=5。对于第一个子列表中的每个值,我想看看是否可以在从左到右读取的每个子列表中找到该值加上 n,其中 n 是该子列表在较大列表中的索引值。那有意义吗? (维特根斯坦在他的坟墓里翻来覆去。)
  • 谢谢您——太好了!我很抱歉我一开始就不清楚。有没有我可以参考的文献来更好地描述未来的这类问题?感谢您回复我的笔记,并更新您的答案!
  • @duhaime 我对文学一窍不通……但我认为作品通常是一句老话:“熟能生巧”;)
【解决方案3】:

我还认为递归表达更好。如果我正确理解了您的问题,这就是我想出的。

a = [ [1,3],[2,4],[3,5],[6],[7] ]
b = [ [1],[2,4],[5] ]
c = [ [1,3],[2,4],[3,5],[6, 4],[5, 7] ]

def foo(data):
    if len(data) == 1:
        return True
    return all(item + 1 in data[1] for item in data[0]) and foo(data[1:])

print foo(a), foo(b), foo(c)
>>> 
False False True
>>> 

【讨论】:

  • 对不起,@wwii,我没有足够清楚地表达我想要的输出。我希望为列表 a 返回 True,因为有一条路径 3、4、5、6、7,每一步都等于先前值 + 1。我真的需要更好的词汇来描述这种现象。递归必须是我所追求的。抱歉,不清楚。
  • 我害怕那个。这看起来像一个图形问题,您想知道是否存在从从左到右的路径。我再吃点面条。
  • @wwii nope,这不是图中的路径,如果是,我的第一个解决方案会起作用:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-30
  • 1970-01-01
  • 1970-01-01
  • 2013-12-02
  • 2012-09-30
  • 2011-12-28
  • 2018-01-18
相关资源
最近更新 更多