Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
找到;重叠“;在2个python列表之间_Python_List - Fatal编程技术网

找到;重叠“;在2个python列表之间

找到;重叠“;在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,

给出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,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]