如何以优雅的方式检查数组是否包含数组?
How to check if array contains array in elegant way?
这是我在 python 中的代码,它检查大数组中的较小子数组是否在其中一个子数组中。我不知道哪个是最大的子数组索引,所以我无法与索引进行比较。也许排序是好的。但是如果有不止一个大的子数组呢?
即我只想在最终数组中包含那些包含较小子数组的大子数组
[[1, 2, 3], [4, 5, 6], [1, 2, 3, 4, 5, 6], [7,8], [9, 10, 11, 12], [7, 8, 9, 10, 11, 12]]
其次,如果元素的顺序可以是随机的,我该怎么办,例如:
[[1, 3, 2], [4, 5, 6], [1, 2, 3, 4, 5, 6], [7,8], [9, 10, 11, 12], [7, 8, 9, 10, 11, 12]]
这是我的代码:
arr1 = [[1, 2, 3], [4, 5, 6], [1, 2, 3, 4, 5, 6], [7,8], [9, 10, 11, 12], [7, 8, 9, 10, 11, 12]]
arr2 = []
arrInd = 0
arrInd2 = len(arr1)
for k in arr1:
for n in reversed(arr1):
if set(n).issubset(set(k)):
arr2.append(k)
print(arr2)
我想看到输出:
[[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12]]
但我有:
[[4, 5, 6], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6], [7, 8], [9, 10, 11, 12], [7, 8, 9, 10, 11, 12], [7, 8, 9, 10, 11, 12], [7, 8, 9, 10, 11, 12]]
更新
因为有很多好的问题我必须添加更多细节。
1)有一个数组数组:
arr1 = [[]]
2) 它包含一些像这些子数组 [1, 2, 3], [4, 5, 6], [4, 6, 5], [7, 8, 9, 10, 11, 12], [11, 12, 13, 14, 15], [1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12, 13, 14, 15], [111, 222, 333], [444, 555], [777, 888], [111, 222, 333, 444, 555], [111, 222, 333, 444, 555, 777, 888], [1000, 2000, 3000]
什么是可能的?
1) 内部数组顺序可能会有所不同:[4, 5, 6], [4, 6, 5]
和 [1, 2, 3, 4, 5, 6]
,所以它不会是数字顺序,实际上在实际数据中(我目前正在测试)甚至可能有字母,比如 A77
, B81
;
2) 数组有大有小,总有一个最大的(或几个),它永远不会与其他最大的数组相交,所以这里 [1, 2, 3, 4, 5, 6]
和 [7, 8, 9, 10, 11, 12, 13, 14, 15]
- 它们不能相互相交,但它们包含一些迷你子阵列;
3)每个大子数组包含一些较小的子数组。但是,并不是所有的和一些小阵法都能独立存在。例如:[1, 2, 3, 4, 5, 6]
包含[1, 2, 3], [4, 5, 6], [4, 6, 5]
,但不包含[7, 8, 9, 10, 11, 12], [11, 12, 13, 14, 15]
或[111, 222, 333]
;
4) 也可能有中间的 "big arrays":[111, 222, 333, 444, 555]
比 [111, 222, 333, 444, 555, 777, 888]
小,所以必须排除第一个 [111, 222, 333, 444, 555]
。
5 *)我想将大数组添加到 arr2
(最终数组)而不是小一次,除了 case *** [1000, 2000, 3000]
到 arr2
(最终数组)
我的代码应该做什么?
它应该通过 arr1 并将不同的元素相互反对,以检测 n 元素是否包含 k 元素,反之亦然,因为它从开始到结束 for k in arr1:
和从结束到开始 for n in reversed(arr1):
更新2.长度比较!
if len(n) < len(k):
for k in arr1:
for n in reversed(arr1):
if len(n) < len(k):
if set(n).issubset(set(k)):
arr2.append(k)
而且离得更近了。其实差不多了,只是重复了,从数量上看,顺序(1)的问题似乎根本不是问题:
arr2 = [[1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12, 13, 14, 15], [7, 8, 9, 10, 11, 12, 13, 14, 15], [111, 222, 333, 444, 555], [111, 222, 333, 444, 555], [111, 222, 333, 444, 555, 777, 888], [111, 222, 333, 444, 555, 777, 888], [111, 222, 333, 444, 555, 777, 888], [111, 222, 333, 444, 555, 777, 888]]
当然可以开始删除重复项并以这种方式再次 运行 arr2 以摆脱 [111, 222, 333, 444, 555]
实际上是 [111, 222, 333, 444, 555, 777, 888]
的一部分,但必须有更优雅的方式。
你可以使用递归函数:
>>> l =[(1, 3, 2), (4, 5, 6), (1, 2, 3, 4, 5, 6), (7, 8), (9, 10, 11, 12), (7, 8, 9, 10, 11, 12)]
>>> def find_max_sub(l):
... for i,j in enumerate(l):
... for t,k in enumerate(l[i+1:],1):
... if set(j).intersection(k):
... return find_max_sub([set(l.pop(i))|set(l.pop(t))]+l)
... return l
...
>>> find_max_sub(l)
[(1, 2, 3, 4, 5, 6), (7, 8, 9, 10, 11, 12)]
您所需要的只是遍历主列表并将列表中的元素与其他元素进行比较,当您发现具有任何交集的子列表时,您弹出这些元素并将新的子列表添加到主列表然后调用函数新列表。
所以您正试图摆脱所有那些只包含也在另一个列表中的元素的列表?
def eachMasterList(allLists):
allSets = [ set(lst) for lst in allLists ]
for lst, s in zip(allLists, allSets):
if not any(s is not otherSet and s < otherSet for otherSet in allSets):
yield lst
要使用该功能,试试这个:
print(list(eachMasterList([[1, 2, 3], [4, 5, 6], [1, 2, 3, 4, 5, 6], [7,8], [9, 10, 11, 12], [7, 8, 9, 10, 11, 12]])))
你有一个很大的列表,你想在其中查找很多列表?就像处理在大集合中查找任何其他类型的对象一样:将它们(或准确地说是合适的版本)存储在一个集合中以允许快速查找。
列表不能是集合元素,但您可以将小列表转换为元组并存储它们:
myindex = set(tuple(sm) for sm in big_list)
然后检查 [1, 3, 4]
是否在你的 big_list
中,你只需说:
if tuple([1, 3, 4]) in myindex:
...
如果你想匹配列表而不考虑顺序(这样 [1, 3, 4]
被认为等于 [3, 1, 4]
),也把它们变成集合。但不是常规集合(它们也不能是集合元素),而是 frozenset
:
myindex = myindex = set(frozenset(sm) for sm in big_list)
就是这样。
你在找这个吗?
def get_subset_list():
for arr in arrays:
others = [x for x in arrays if x != arr]
for other in others:
for val in arr:
if val not in other:
break
else:
break
else:
yield arr
import json
x = get_subset_list()
print set([json.dumps(y) for y in x])
您可以简单地比较两个数组,将它们转换为 字符串 然后通过 __contains__
进行比较
print (''.join(arr1).__contains__(''.join(arr2)))
这是我在 python 中的代码,它检查大数组中的较小子数组是否在其中一个子数组中。我不知道哪个是最大的子数组索引,所以我无法与索引进行比较。也许排序是好的。但是如果有不止一个大的子数组呢? 即我只想在最终数组中包含那些包含较小子数组的大子数组
[[1, 2, 3], [4, 5, 6], [1, 2, 3, 4, 5, 6], [7,8], [9, 10, 11, 12], [7, 8, 9, 10, 11, 12]]
其次,如果元素的顺序可以是随机的,我该怎么办,例如:
[[1, 3, 2], [4, 5, 6], [1, 2, 3, 4, 5, 6], [7,8], [9, 10, 11, 12], [7, 8, 9, 10, 11, 12]]
这是我的代码:
arr1 = [[1, 2, 3], [4, 5, 6], [1, 2, 3, 4, 5, 6], [7,8], [9, 10, 11, 12], [7, 8, 9, 10, 11, 12]]
arr2 = []
arrInd = 0
arrInd2 = len(arr1)
for k in arr1:
for n in reversed(arr1):
if set(n).issubset(set(k)):
arr2.append(k)
print(arr2)
我想看到输出:
[[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12]]
但我有:
[[4, 5, 6], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6], [7, 8], [9, 10, 11, 12], [7, 8, 9, 10, 11, 12], [7, 8, 9, 10, 11, 12], [7, 8, 9, 10, 11, 12]]
更新
因为有很多好的问题我必须添加更多细节。
1)有一个数组数组:
arr1 = [[]]
2) 它包含一些像这些子数组 [1, 2, 3], [4, 5, 6], [4, 6, 5], [7, 8, 9, 10, 11, 12], [11, 12, 13, 14, 15], [1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12, 13, 14, 15], [111, 222, 333], [444, 555], [777, 888], [111, 222, 333, 444, 555], [111, 222, 333, 444, 555, 777, 888], [1000, 2000, 3000]
什么是可能的?
1) 内部数组顺序可能会有所不同:[4, 5, 6], [4, 6, 5]
和 [1, 2, 3, 4, 5, 6]
,所以它不会是数字顺序,实际上在实际数据中(我目前正在测试)甚至可能有字母,比如 A77
, B81
;
2) 数组有大有小,总有一个最大的(或几个),它永远不会与其他最大的数组相交,所以这里 [1, 2, 3, 4, 5, 6]
和 [7, 8, 9, 10, 11, 12, 13, 14, 15]
- 它们不能相互相交,但它们包含一些迷你子阵列;
3)每个大子数组包含一些较小的子数组。但是,并不是所有的和一些小阵法都能独立存在。例如:[1, 2, 3, 4, 5, 6]
包含[1, 2, 3], [4, 5, 6], [4, 6, 5]
,但不包含[7, 8, 9, 10, 11, 12], [11, 12, 13, 14, 15]
或[111, 222, 333]
;
4) 也可能有中间的 "big arrays":[111, 222, 333, 444, 555]
比 [111, 222, 333, 444, 555, 777, 888]
小,所以必须排除第一个 [111, 222, 333, 444, 555]
。
5 *)我想将大数组添加到 arr2
(最终数组)而不是小一次,除了 case *** [1000, 2000, 3000]
到 arr2
(最终数组)
我的代码应该做什么?
它应该通过 arr1 并将不同的元素相互反对,以检测 n 元素是否包含 k 元素,反之亦然,因为它从开始到结束 for k in arr1:
和从结束到开始 for n in reversed(arr1):
更新2.长度比较!
if len(n) < len(k):
for k in arr1:
for n in reversed(arr1):
if len(n) < len(k):
if set(n).issubset(set(k)):
arr2.append(k)
而且离得更近了。其实差不多了,只是重复了,从数量上看,顺序(1)的问题似乎根本不是问题:
arr2 = [[1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12, 13, 14, 15], [7, 8, 9, 10, 11, 12, 13, 14, 15], [111, 222, 333, 444, 555], [111, 222, 333, 444, 555], [111, 222, 333, 444, 555, 777, 888], [111, 222, 333, 444, 555, 777, 888], [111, 222, 333, 444, 555, 777, 888], [111, 222, 333, 444, 555, 777, 888]]
当然可以开始删除重复项并以这种方式再次 运行 arr2 以摆脱 [111, 222, 333, 444, 555]
实际上是 [111, 222, 333, 444, 555, 777, 888]
的一部分,但必须有更优雅的方式。
你可以使用递归函数:
>>> l =[(1, 3, 2), (4, 5, 6), (1, 2, 3, 4, 5, 6), (7, 8), (9, 10, 11, 12), (7, 8, 9, 10, 11, 12)]
>>> def find_max_sub(l):
... for i,j in enumerate(l):
... for t,k in enumerate(l[i+1:],1):
... if set(j).intersection(k):
... return find_max_sub([set(l.pop(i))|set(l.pop(t))]+l)
... return l
...
>>> find_max_sub(l)
[(1, 2, 3, 4, 5, 6), (7, 8, 9, 10, 11, 12)]
您所需要的只是遍历主列表并将列表中的元素与其他元素进行比较,当您发现具有任何交集的子列表时,您弹出这些元素并将新的子列表添加到主列表然后调用函数新列表。
所以您正试图摆脱所有那些只包含也在另一个列表中的元素的列表?
def eachMasterList(allLists):
allSets = [ set(lst) for lst in allLists ]
for lst, s in zip(allLists, allSets):
if not any(s is not otherSet and s < otherSet for otherSet in allSets):
yield lst
要使用该功能,试试这个:
print(list(eachMasterList([[1, 2, 3], [4, 5, 6], [1, 2, 3, 4, 5, 6], [7,8], [9, 10, 11, 12], [7, 8, 9, 10, 11, 12]])))
你有一个很大的列表,你想在其中查找很多列表?就像处理在大集合中查找任何其他类型的对象一样:将它们(或准确地说是合适的版本)存储在一个集合中以允许快速查找。
列表不能是集合元素,但您可以将小列表转换为元组并存储它们:
myindex = set(tuple(sm) for sm in big_list)
然后检查 [1, 3, 4]
是否在你的 big_list
中,你只需说:
if tuple([1, 3, 4]) in myindex:
...
如果你想匹配列表而不考虑顺序(这样 [1, 3, 4]
被认为等于 [3, 1, 4]
),也把它们变成集合。但不是常规集合(它们也不能是集合元素),而是 frozenset
:
myindex = myindex = set(frozenset(sm) for sm in big_list)
就是这样。
你在找这个吗?
def get_subset_list():
for arr in arrays:
others = [x for x in arrays if x != arr]
for other in others:
for val in arr:
if val not in other:
break
else:
break
else:
yield arr
import json
x = get_subset_list()
print set([json.dumps(y) for y in x])
您可以简单地比较两个数组,将它们转换为 字符串 然后通过 __contains__
print (''.join(arr1).__contains__(''.join(arr2)))