如果列表在其他列表中的布尔表达式
Posted
技术标签:
【中文标题】如果列表在其他列表中的布尔表达式【英文标题】:Boolean expression for if list is within other list 【发布时间】:2016-12-17 13:27:44 【问题描述】:检查一个列表是否在另一个列表中的有效方法是什么?比如:
[2,3] in [1,2,3,4] #evaluates True
[1,5,4] in [5,1,5,4] #evaluates True
[1,2] in [4,3,2,1] #evaluates False
列表中的顺序很重要。
【问题讨论】:
第一个列表中的元素是否需要在第二个列表中连续?例如,[1,2] in [1,3,2]
应该返回什么?
false,因为必须是连续的
这个问题与***.com/questions/3313590/… 完全不同,***.com/questions/3313590/… 假设数据是二进制并使用连接。这里的数据可以是任何数值,例如[2, 55, 100]。在这种情况下,“重复”问题中建议的解决方案不适用。
@Alexander - 该问题的 OP 并未仅指定二进制数据,并且有适用于 this 数据的答案/解决方案。 - 特别是投票最多的答案.
其实,***.com/questions/3313590/… 的问题和这个问题是一样的,那里最受好评的答案也适用于此(巧合的是,与我下面的答案相同)。
【参考方案1】:
def check_ordered_sublist_in_list(sub_list, main_list):
sub_list = np.array(sub_list)
main_list = np.array(main_list)
return any(all(main_list[n:(n + len(sub_list))] == sub_list)
for n in range(0, len(main_list) - len(sub_list) + 1))
>>> check_ordered_sublist_in_list([2, 3], [1, 2, 3, 4])
True
>>> check_ordered_sublist_in_list([1, 5, 4], [5, 1, 5, 4])
True
>>> check_ordered_sublist_in_list([1, 2], [4, 3, 2, 1])
False
这会将列表转换为 numpy 数组(为了计算效率),然后使用切片检查 sub_list
是否包含在切片中。任何成功都返回 True。
【讨论】:
这似乎是对numpy
的滥用。构建np.array
s 是一项相当昂贵的操作。这很可能会否定使用 numpy
来执行一些简单的切片所获得的任何计算效率(尤其是因为示例中的列表非常小)。
@pzp 可能,但在这个简单的示例中列表很小。实际用例往往要复杂得多。不过,我同意@mfripp 提出的is_in
解决方案效率更高。
在函数名中使用“ordered_sublist”似乎是多余的——不是所有的列表都在 Python 中排序吗?
@martineau 是的,所有列表都是有序的。函数标题旨在阐明 [1, 2] 在 [1, 2, 3, 4] 中,但 [2, 1] 不在。正如 OP 所阐明的那样,排序很重要,并且可以区分无序的集合。例如,初始回复错误地使用了集合。
OP 从不询问无序集合,仅当列表是另一个列表的子列表时。由于两者都是列表,因此都按定义排序。【参考方案2】:
你可以用这个:
def is_in(short, long):
return any(short==long[i:i+len(short)] for i in range(len(long)-len(short)+1))
is_in([2,3], [1,2,3,4]) # True
is_in([1,5,4], [5,1,5,4]) # True
is_in([1,2], [4,3,2,1]) # False
如果你真的很在意速度,这些表达式会快 20-30%:
def segments(long, length):
return [long[i:i+length] for i in range(len(long)-length+1)]
def is_in_seg(short, long):
return short in segments(long, len(short))
is_in_seg([1,5,4], [5,1,5,4]) # true
[1,5,4] in segments([5,1,5,4], 3) # true
这比列表快 47%,但它使用元组而不是列表:
import itertools
def segments_zip(long, length):
return itertools.izip(*[long[i:] for i in xrange(length)])
(2,3) in segments_zip((1,2,3,4), 2) # True
(1,5,4) in segments_zip((5,1,5,4), 3) # True
(1,2) in segments_zip((4,3,2,1), 2) # False
额外的速度来自使用 itertools.izip,它可以在找到匹配项时停止生成段;从使用 xrange 避免创建整个范围列表;以及使用元组,它通常比列表稍快。但是,如果您必须将列表转换为元组才能使用它,那么微小的速度优势就会消失。
【讨论】:
以上是关于如果列表在其他列表中的布尔表达式的主要内容,如果未能解决你的问题,请参考以下文章