2016-08-04 5 views
1

Предположим, у меня есть два списка строк. Я хочу изменить порядок второго списка, получив элемент, который больше всего похож на соответствующий элемент первого списка.Соответствующие элементы двух списков, которые почти одинаковы

Я уже делаю это:

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
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 Рауль Баррера, в соответствующей модификации выше будет:

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'] 
+0

Спасибо! Это именно то, что я хочу :) – Maxline

+0

Это решение не справляется с этими данными: 'list1 = ['aaaa', 'bbbb', 'cccc', 'dddd', 'eeee', 'ffff', 'gggg', 'hhhh ',' iiii ',' jjjj '] * 2 list2 = [' eeez ',' fffz ',' dddz ',' cccz ',' iiiz ',' jjjz ',' aaaz ',' gggz ',' hhhz ',' bbbz '] * 2 –

+0

Спасибо @JoseRaulBarreras исправлено –

2

Мои два центов. И да, то решение может быть более вещий ...

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. Клюгерфорд не справляется с этими данными.