在两个不同长度的非相同未排序 python 列表中处理 matching/joining 元素的最佳方法是什么?

What is the best approach to matching/joining elements in two non-identical unsorted python lists of different lengths?

例如,我有以下 python 列表:

a = [1,2,1,3,2,1,1,1,2,1,1,1,1,1,3,1,2]  
b = [1,1,2,1,3,1,1,1,1,2,2,1,1,1,1,3,1,2]  

我想获取可以自信匹配的元素的索引元组,例如:

[(0,0), (1,2), (2,3), (3,4), (8,9), (14,15), (15,16), (16,17)]  

数据代表了记录到达和离开队列的人数,但数据也不是完美的,所以a和b的总和不匹配,人也不总是需要按照他们到达的顺序离开。

我知道它取决于几个变量(或阈值参数),但我只是在寻找有关如何最好地解决问题的建议。我很乐意使用 Pandas/Numpy/Scipy 来完成这项工作。

我发现这很难解释。靠眼睛,我很容易匹配部分序列,例如1,2,1,3。不过,找到一个好的算法方法并不是那么容易。

我不完全理解你的输出,但要按顺序获取匹配的元素索引:

a = [1, 2, 1, 3, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 3, 1, 2]
b = [1, 1, 2, 1, 3, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 3, 1, 2]
from collections import defaultdict, deque

d = defaultdict(deque)
for i, j in enumerate(b):
    d[j].append(i)

print([(i, d[j].popleft()) for i, j in enumerate(a)])

我能匹配你的输出的唯一方法是我们考虑不是序列的元素:

from itertools import groupby 
from operator import itemgetter

def pairs(a, b):
    for (k, v) in (groupby(enumerate(a), key=itemgetter(1))):
        data = next(v)
        if not next(v, None):
            ind, val = data
            if b[ind] == val:
                yield (ind, ind)
            elif val == b[ind + 1]:
                yield (ind, ind + 1)

 print(list(pairs(a, b)))

哪个会给你:

[(0, 0), (1, 2), (2, 3), (3, 4), (8, 9), (14, 15), (15, 16), (16, 17)]

我终于意识到 Python 有 difflib 库来处理这种事情!

a = [1, 2, 1, 3, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 3, 1, 2]  
b = [1, 1, 2, 1, 3, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 3, 1, 2]  

from difflib import SequenceMatcher  

s = SequenceMatcher(None, a, b, autojunk=False)  

matched_element_indices = []
for m in s.get_matching_blocks():
    matched_element_indices += [(m.a+i,m.b+i) for i in range(m.size)]

它产生这个:

In : matched_element_indices
Out: [(0, 1), (1, 2), (2, 3), (3, 4), (5, 6), (6, 7), (7, 8), (8, 9), 
           (10, 11), (11, 12), (12, 13), (13, 14), (14, 15), (15, 16), (16, 17)]