说我有两个列表(长度相同):
l0 = [0, 4, 4, 4, 0, 0, 0, 8, 8, 0]
l1 = [0, 1, 1, 1, 0, 0, 0, 8, 8, 8]
对于按元素进行比较的这些交集和并集,我有以下规则:
# union and intersect
uni = [0]*len(l0)
intersec = [0]*len(l0)
for i in range(len(l0)):
if l0[i] == l1[i]:
uni[i] = l0[i]
intersec[i] = l0[i]
else:
intersec[i] = 0
if l0[i] == 0:
uni[i] = l1[i]
elif l1[i] == 0:
uni[i] = l0[i]
else:
uni[i] = [l0[i], l1[i]]
因此,所需的输出是:
uni: [0, [4, 1], [4, 1], [4, 1], 0, 0, 0, 8, 8, 8]
intersec: [0, 0, 0, 0, 0, 0, 0, 8, 8, 0]
虽然可行,但我需要使用数百个非常大的列表(每个列表包含数千个元素)来完成此操作,因此我正在寻找一种矢量化方法。我尝试使用np.where
和各种屏蔽策略,但是进展并不很快。任何建议都将受到欢迎。
*编辑*
关于
uni: [0, [4, 1], [4, 1], [4, 1], 0, 0, 0, 8, 8, 8]
与
uni: [0, [4, 1], [4, 1], [4, 1], 0, 0, 0, 8, 8, [0, 8]]
在我的脑海中,我仍在与8对[0,8]作斗争。列表来自系统注释中的BIO标签(请参见IOB labeling of text chunks),其中每个列表元素是文档中的字符索引,而vakue是分配的枚举标签。 0代表没有注释的标签(即,用于确定混淆矩阵中的否定标签);非零元素代表为该字符分配的枚举标签。由于我忽略了真正的负面因素,因此我想我可以说8等于[0,8]。至于这是否简化了事情,我还不确定。
*编辑2 *
我正在使用[0, 8]
来简化事情,并使intersection
和union
的定义与集合论保持一致。
答案 0 :(得分:2)
我不会把它们称为“交集”和“联合”,因为这些操作在集合上具有明确定义的含义,而您要执行的操作都不是它们。
但是,要做您想做的事情:
l0 = [0, 4, 4, 4, 0, 0, 0, 8, 8, 0]
l1 = [0, 1, 1, 1, 0, 0, 0, 8, 8, 8]
values = [
(x
if x == y else 0,
0
if x == y == 0
else x if y == 0
else y if x == 0
else [x, y])
for x, y in zip(l0, l1)
]
result_a, result_b = map(list, zip(*values))
print(result_a)
print(result_b)
这对于数千个甚至数百万个元素来说已经足够了,因为该操作是如此基础。当然,如果我们要谈论的是数十亿美元,您可能还是要看一下numpy。
答案 1 :(得分:0)
半矢量化的联合和全交集解决方案:
import numpy as np
l0 = np.array(l0)
l1 = np.array(l1)
intersec = np.zeros(l0.shape[0])
intersec_idx = np.where(l0==l1)
intersec[intersec_idx] = l0[intersec_idx]
intersec = intersec.astype(int).tolist()
union = np.zeros(l0.shape[0])
union_idx = np.where(l0==l1)
union[union_idx] = l0[union_idx]
no_union_idx = np.where(l0!=l1)
union = union.astype(int).tolist()
for idx in no_union_idx[0]:
union[idx] = [l0[idx], l1[idx]]
和输出:
>>> intersection
[0, 0, 0, 0, 0, 0, 0, 8, 8, 0]
>>> union
[0, [4, 1], [4, 1], [4, 1], 0, 0, 0, 8, 8, [0, 8]]
注意:我认为您原来的工会解决方案不正确。看到最后一个输出8 vs [0,8]
答案 2 :(得分:0)
在处理大型数据集时采用内存有效的做法
l0 = [0, 4, 4, 4, 0, 0, 0, 8, 8, 0]
l1 = [0, 1, 1, 1, 0, 0, 0, 8, 8, 8]
v = zip(l0, l1)
intersec = []
uni = []
for _ in range(len(l0)):
x = next(v)
intersec.append(x[0] if x[0] == x[1] != 0 else 0)
uni.append([x[0],x[1]] if x[0] != x[1] else x[0])
print(intersec)
print(uni)
输出
[0, 0, 0, 0, 0, 0, 0, 8, 8, 0]
[0, [4, 1], [4, 1], [4, 1], 0, 0, 0, 8, 8, [0, 8]]