两个列表的匹配元素几乎相同

时间:2016-08-04 21:41:52

标签: python difflib

假设我有两个字符串列表。我想通过获取最类似于第一个列表的相应元素的元素来重新排序第二个列表。

我已经这样做了:

import difflib

list1 = ['aaaa', 'bbbb', 'cccc', 'dddd', 'eeee', 'ffff', 'gggg', 'hhhh', 'iiii', 'jjjj']
list2 = ['eeez', 'fffz', 'dddz', 'cccz', 'iiiz', 'jjjz', 'aaaz', 'gggz', 'hhhz', 'bbbz']

len = len(list1)
i = 0
while i < len:
    j = 0
    while j < len:
        if difflib.SequenceMatcher(None, list1[i], list2[j]).ratio() > 0.5:
            eltMove = list2.pop(j)
            list2.insert(i, eltMove)
            break
        j += 1
    i += 1

print(list2)

输出:

['aaaz', 'bbbz', 'cccz', 'dddz', 'eeez', 'fffz', 'gggz', 'hhhz', 'iiiz', 'jjjz']

但是在某些情况下,它在list2中有一个元素与list1中的元素匹配时会起作用,这会破坏循环并跳过下一个元素,即使它们可以更好地匹配。

2 个答案:

答案 0 :(得分:2)

while i  < len:
    j = 0
    new_l = []
    while j < len:
        new_l.append(difflib.SequenceMatcher(None, list1[i], list2[j]).ratio())
        j += 1
    ind = new_l.index(max(new_l))
    eltMove = list2.pop(ind)
    list2.insert(i, eltMove)
    i += 1

它存储比率,然后计算最大值,找出最大值的索引,然后弹出/插入。

希望这是你需要的

for i, a in enumerate(list1):
    new_l = [difflib.SequenceMatcher(None, a, b).ratio() for b in list2]
    ind = new_l.index(max(new_l))
    eltMove = list2.pop(ind)
    list2.insert(i, eltMove)

缩短代码

考虑到@Jose Raul Barreras的回复,对上述内容的适当修改将是:

tmp = []
for i, a in enumerate(list1):
    new_l = [difflib.SequenceMatcher(None, a, b).ratio() for b in list2]
    ind = new_l.index(max(new_l))
    eltMove = list2.pop(ind)
    tmp.append(eltMove)

>>> tmp
['aaaz', 'bbbz', 'cccz', 'dddz', 'eeez', 'fffz', 'gggz', 'hhhz', 'iiiz', 'jjjz', 
 'aaaz', 'bbbz', 'cccz', 'dddz', 'eeez', 'fffz', 'gggz', 'hhhz', 'iiiz', 'jjjz']

答案 1 :(得分:2)

我的两分钱。是的,解决方案可能更加pythonic ...

import difflib

def closest_list(list1, list2):
    tmp_list = list2
    res = []
    for elem1 in list1:
        best_value = 0
        best = None
        position = None
        for i, elem2 in enumerate(list2):
            current_value = difflib.SequenceMatcher(None, elem1, elem2).ratio()
            if  (current_value > best_value) and (elem2 in tmp_list):
                best_value = current_value
                best = elem2
                position = i
        del tmp_list[position]
        res.append(best)
    return res

a = ['aaaa', 'bbbb', 'cccc', 'dddd', 'eeee', 'ffff', 'gggg', 'hhhh', 'iiii', 'jjjj']*2
b = ['eeez', 'fffz', 'dddz', 'cccz', 'iiiz', 'jjjz', 'aaaz', 'gggz', 'hhhz', 'bbbz']*2
print(closest_list(a,b))

<强>输出:

  

['aaaz','bbbz','cccz','dddz','eeez','fffz','gggz','hhhz',   'iiiz','jjjz','aaaz','bbbz','cccz','dddz','eeez','fffz',   'gggz','hhhz','iiiz','jjjz']

@M给出的解决方案。克鲁格福德对此数据失败了。