我有一个嵌套列表,每个第二个元素都有不同的长度:
lst = [[a,bcbcbcbcbc],[e,bbccbbccb],[i,ccbbccbb],[o,cbbccbb]]
我的输出是具有这种外观的数据帧的csv:
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 :(得分:1)
根据Python的文档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
,if语句将查看以下索引:
(0,1)
(1,2)
(2,3)<--
在这种情况下,3是你的问题。
要解决您的问题,请从[0, len(string) - 1]
答案 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
是{{1}的版本}})。然后你可以除以字符串长度中较小的一个(如果你想惩罚长度差异,可以更大):
0
还有一个更明显的问题,即你用两个参数调用common_letters = sum(c1 == c2 for c1, c2 in zip(string1, string2))
new_score = common_letters * 100 / min(len(string1), len(string2))
。如果你真的想要附加一个2元组,你需要一组额外的括号:
append