2016-03-27 6 views
0

У меня есть вложенный список, с каждым вторым элементом, имеющие различные длинами:Счетные сходства нескольких элементов с неравной длиной вложенного списка

lst = [[a,bcbcbcbcbc],[e,bbccbbccb],[i,ccbbccbb],[o,cbbccbb]] 

Моего выходом является CSV из dataframe с этим взглядом:

comparison  similarity_score 
    a:e   *some score  
    a:i   *some score 
    a:o   *some score 
    e:i   *some score 
    e:o   *some score 
    i:o   *some score 

мой код:

similarity = [] 
for i in lst: 
    name = i[0] 
    string = i[1] 
    score = 0.0 
    length =(len(string)) 
    for i in range(length): 
     if string[i]==string[i+1]: 
      score += 1.0 
    new_score = (100.0*score)/length 
    name_seq = name[i] + ':' + name[i+1] 
    similarity.append(name_seq,new_score) 

similarity.pdDataFrame(similarity, columns = ['comparison' , 'similarity_score']) 
similarity.to_csv('similarity_score.csv') 

но я ПОЛУЧАТЬ ошибку:

if codes[i]==codes[i+1]: 
      IndexError: string index out of range 

любой совет? благодаря!

+0

Где инициализируется numPlaces? коды [i] == коды [i + 1] не отображаются в вашем фрагменте кода, если вы не имеете в виду строку [i] == string [i + 1] – elhefe

+0

Что такое 'numPlaces' (возможно, это должно быть' length ')? И почему строка в вашем исключении не соответствует ни одной из строк в коде, который вы указали? В любом случае, я думаю, вы запутались в 'i', потому что вы используете одно и то же имя переменной для двух разных вещей в разное время. И если 'name'' '' 'в вашем списке, то место, которое вы делаете' name [i + 1] ', не имеет большого смысла. – Blckknght

+0

@Blckknght благодарит вас за исправления. Я должен признать, что я очень смущен тем, что я в цикле for. –

ответ

1

Согласно документации Пайтона range делает следующее пример:

>>>range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

В коде (предполагающие имена переменных не изменились):

... 
length =(len(string))   # For an input of 'bcb' length will be 3 
for i in range(length):   # For an input of 'bcb' range will be [0, 1, 2] 
    if string[i]==string[i+1]: # When i == 2 i + 1 == 3 which gives you the 
           # IndexError: string index out of range 
... 

Другими словами, данный вход bcb, в вашем отчете будут отображаться следующие индексы:

(0, 1)
(1, 2)
(2, 3) <-- 3 в этом случае является вашей проблемой.

Чтобы устранить проблему итерацию из [0, len(string) - 1]

1

Я думаю, что ваш большой проблемой является то, что на самом высоком уровне, вы просто итерация на одной name,string пары в то время, а не пару name,string пар, как вы хотите, чтобы увидеть в вашем выводе (как показано парными именами a:e).

Вы пытаетесь индексировать значения name и string позже, но это не значит, что вы не достигаете того, что хотите (сравнивая две строки друг с другом, чтобы вычислить оценку), поскольку вы получаете доступ только к соседним символам в ту же строку. Исключением, которое вы получаете, является то, что i+1 может покинуть конец строки. Еще одна путаница, поскольку вы используете i как для индекса во внутреннем цикле, так и для элементов, взятых из внешнего цикла (пары name, string).

Чтобы получить пар пар, я предлагаю использовать itertools.combinations:

import itertools 

for [name1, string1], [name2, string2] in itertools.combinations(lst, 2): 

Теперь вы можете использовать два имени и две строковые переменные в остальной части цикла.

Я не совсем уверен, что понимаю, как вы хотите сравнить строки, чтобы получить свой результат, поскольку они не такие же, как и одна. Если вы хотите сравнить только начальные части строк (и игнорировать конечный бит более длинного), вы можете использовать zip, чтобы получить пары соответствующих символов между двумя строками. Затем вы можете сравнить их в выражении генератора и добавить результаты bool (True - специальная версия целого 1 и False - это версия 0).Затем можно разделить на меньшее из длины струны (или, может быть больше, если вы хотите, чтобы оштрафовать разницы длины):

common_letters = sum(c1 == c2 for c1, c2 in zip(string1, string2)) 
new_score = common_letters * 100/min(len(string1), len(string2)) 

Там еще один очевидный вопрос, где вы звоните append с двумя аргументами. Если вы действительно хотите добавить 2-кортеж, вам нужен дополнительный набор круглых скобок:

similarity.append((name_seq, new_score)) 

 Смежные вопросы

  • Нет связанных вопросов^_^