找到;重叠“;在2个python列表之间
给出2个列表:找到;重叠“;在2个python列表之间,python,list,Python,List,给出2个列表: a = [3,4,5,5,5,6] b = [1,3,4,4,5,5,6,7] 我想找到“重叠”: 如果我能提取a和b中不在c中的部分的“余数”,我也很乐意 a_remainder = [5,] b_remainder = [1,4,7,] 注: a有三个5,b有两个。 b有两个4,a有一个 结果列表c应该有两个5(受列表b限制)和一个4(受列表a限制) 这给了我想要的,但我忍不住认为还有更好的方法 import copy a = [3,4,5,5,5,6] b = [1,
a = [3,4,5,5,5,6]
b = [1,3,4,4,5,5,6,7]
我想找到“重叠”:
如果我能提取a和b中不在c中的部分的“余数”,我也很乐意
a_remainder = [5,]
b_remainder = [1,4,7,]
注:
a有三个5,b有两个。
b有两个4,a有一个
结果列表c应该有两个5(受列表b限制)和一个4(受列表a限制)
这给了我想要的,但我忍不住认为还有更好的方法
import copy
a = [3,4,5,5,5,6]
b = [1,3,4,4,5,5,6,7]
c = []
for elem in copy.deepcopy(a):
if elem in b:
a.pop(a.index(elem))
c.append(b.pop(b.index(elem)))
# now a and b both contain the "remainders" and c contains the "overlap"
另一方面,对于我所要求的,还有什么比“重叠”和“余数”更准确的名称呢?在集合语言中,重叠是“交叉”,余数是“集合差”。如果您有不同的项目,您就不必自己进行这些操作,如果您感兴趣,请查看 因为我们没有使用不同的元素,所以您的方法是合理的。如果您想让它运行得更快,可以为每个列表创建一个字典,并将数字映射到每个数组中的元素数量(例如,在a、3->1、4->1、5->2等中)。然后,您将遍历映射a,确定该字母是否存在,减少其计数并将其添加到新列表中 未经测试的代码,但这就是想法
def add_or_update(map,value):
if value in map:
map[value]+=1
else
map[value]=1
b_dict = dict()
for b_elem in b:
add_or_update(b_dict,b_elem)
intersect = []; diff = [];
for a_elem in a:
if a_elem in b_dict and b_dict[a_elem]>0:
intersect.add(a_elem);
for k,v in diff:
for i in range(v):
diff.add(k);
但是如果您需要c
来复制,并且顺序对您很重要,您可以使用python集查找
intersection = set(a) & set(b)
a_remainder = set(a) - set(b)
b_remainder = set(b) - set(a)
kerio在freenode上的#python中的回应:
[ i for i in itertools.chain.from_iterable([k] * v for k, v in \
(Counter(a) & Counter(b)).iteritems())
]
好的,冗长,但有点酷(精神上类似于
系列。Counter
创意,但更多是自制的):
基本思想是将每个列表制作成一个新的列表,该列表为每个对象附加一个计数器,并对其进行编号以说明重复项——这样您就可以对这些元组使用set
操作了
要稍微不那么冗长:
aa = set(flatten(enumerate(g) for k, g in it.groupby(a)))
bb = set(flatten(enumerate(g) for k, g in it.groupby(b)))
# aa = set([(0, 3), (0, 4), (0, 5), (0, 6), (1, 5), (2, 5)])
# bb = set([(0, 1), (0, 3), (0, 4), (0, 5), (0, 6), (0, 7), (1, 4), (1, 5)])
cc = aa.intersection(bb)
# cc = set([(0, 3), (0, 4), (0, 5), (0, 6), (1, 5)])
c = sorted(v for u,v in cc)
# c = [3, 4, 5, 5, 6]
——生成包含相同元素的列表列表 (但是由于语法需要groupby
来提取每个列表)g表示k,g在其中。groupby(a)
——为每个子列表的每个元素追加一个计数器枚举
——创建单个列表展平
——转换为集合集合
——查找公共元素交叉点
——去掉计数器并对结果进行排序sorted(v代表u,v代表cc)
aacc
和bbcc
,但我不知道你从哪里得到a_余数=[4]
:
sorted(v for u,v in aa-cc)
# [5]
sorted(v for u,v in bb-cc)
# [1, 4, 7]
我认为您实际上不应该使用这个解决方案,但我利用这个机会练习了lambda函数,下面是我的想法:) 我很确定这会简化一点(不需要
default\u集
lambda),但我用Python2.5进行了测试
以下是计算中使用的一些中间值,以防有人想了解这一点:
dedup(a) = [set([3, 4, 5, 6]), set([5]), set([5])]
dedup(b) = [set([1, 3, 4, 5, 6, 7]), set([4, 5])]
deduped = [(set([3, 4, 5, 6]), set([1, 3, 4, 5, 6, 7])), (set([5]), set([4, 5])), (set([5]), set([]))]
Python2.7中提供的
collection.Counter
可用于实现完全满足您需要的多集
a = [3,4,5,5,5,6]
b = [1,3,4,4,5,5,6,7]
a_multiset = collections.Counter(a)
b_multiset = collections.Counter(b)
overlap = list((a_multiset & b_multiset).elements())
a_remainder = list((a_multiset - b_multiset).elements())
b_remainder = list((b_multiset - a_multiset).elements())
print overlap, a_remainder, b_remainder
试试“一个比较任意类型序列对的灵活类”
快速尝试:
a = [3,4,5,5,5,6]
b = [1,3,4,4,5,5,6,7]
sm = difflib.SequenceMatcher(None, a, b)
c = []
a_remainder = []
b_remainder = []
for tag, i1, i2, j1, j2 in sm.get_opcodes():
if tag == 'replace':
a_remainder.extend(a[i1:i2])
b_remainder.extend(b[j1:j2])
elif tag == 'delete':
a_remainder.extend(a[i1:i2])
elif tag == 'insert':
b_remainder.extend(b[j1:j2])
elif tag == 'equal':
c.extend(a[i1:i2])
现在
>>> print c
[3, 4, 5, 5, 6]
>>> print a_remainder
[5]
>>> print b_remainder
[1, 4, 7]
在集合论中,“重叠”称为交集,“剩余”称为差集。不幸的是,你不能用Python集在一行中完成这件事,因为你有重复的值。你可以使用
list(a)
而不是copy.deepcopy(a)
在这里。应该是a(余数=[5,]
,对吗?你也可以使用a[:]
而不是copy.deepcopy(a)
。安德鲁·贾菲:你是对的。我会调整问题以避免混淆,以防其他人出现。这是一个好主意,但该人的数据不是有效集,有重复,并考虑到这一点。出于好奇,为什么会投反对票?与其他被否决的答案不同,我的答案是正确的。我知道这很难理解,但这就是为什么有免责声明的原因。我之所以发布这篇文章,是因为我认为其他人会对使用集合运算的解决方案感兴趣,即使它有点晦涩难懂。解决方案只有在您能够独立验证的情况下才是正确的。否则,您将依赖作者和您能想到的几个示例来测试它。您的解决方案对读者来说是一个极好的思维练习,但您不希望代码验证阶段比代码编写阶段长。;)我不知道为什么这件事被否决了。这对我有用。
dedup(a) = [set([3, 4, 5, 6]), set([5]), set([5])]
dedup(b) = [set([1, 3, 4, 5, 6, 7]), set([4, 5])]
deduped = [(set([3, 4, 5, 6]), set([1, 3, 4, 5, 6, 7])), (set([5]), set([4, 5])), (set([5]), set([]))]
a = [3,4,5,5,5,6]
b = [1,3,4,4,5,5,6,7]
a_multiset = collections.Counter(a)
b_multiset = collections.Counter(b)
overlap = list((a_multiset & b_multiset).elements())
a_remainder = list((a_multiset - b_multiset).elements())
b_remainder = list((b_multiset - a_multiset).elements())
print overlap, a_remainder, b_remainder
a = [3,4,5,5,5,6]
b = [1,3,4,4,5,5,6,7]
sm = difflib.SequenceMatcher(None, a, b)
c = []
a_remainder = []
b_remainder = []
for tag, i1, i2, j1, j2 in sm.get_opcodes():
if tag == 'replace':
a_remainder.extend(a[i1:i2])
b_remainder.extend(b[j1:j2])
elif tag == 'delete':
a_remainder.extend(a[i1:i2])
elif tag == 'insert':
b_remainder.extend(b[j1:j2])
elif tag == 'equal':
c.extend(a[i1:i2])
>>> print c
[3, 4, 5, 5, 6]
>>> print a_remainder
[5]
>>> print b_remainder
[1, 4, 7]