比较嵌套列表的相似性

问题描述 投票:1回答:3

我有一个3个列表的列表,每个列表中都有1个列表。

data_set = [
    ['AB12345',['T','T','C','C','A','C','A','G','C','T','T','T','T','C']],
    ['AB12346',['T','T','C','C','A','C','C','G','C','T','C','T','T','C']],
    ['AB12347',['T','G','C','C','A','C','G','G','C','T','T','C','T','C']]
]

我有一个比较方法,它将给我包含字符的列表的相似之处,而不是id。

def compare(_from, _to):
    similarity = 0
    length = len(_from)
    if len(_from) != len(_to):
        raise Exception("Cannot be compared due to different length.")
    for i in range(length):
        if _from[i] == _to[i]:
            similarity += 1
    return similarity / length * 100

compare(data_set[0][1], data_set[1][1])

通过使用比较方法,我使用for循环来比较“a”列表与其他列表,如“a”与“a”相比,“a”与“b”相比,“a”与“c”相比较。

for i in range(len(data_set)):
    data_set[i].append(compare(data_set[0][1], data_set[i][1]))
    print(round(data_set[i][2], 2), end=", ")

但是在完成第一个列表与其他列表及其自身的比较之后,我如何循环到第二个列表和第三个列表并继续与其他列表进行比较以获得它们的相似之处?例如,(“b”与“a”相比,“b”与“b”相比,“b”与“c”相比)和(“c”与“a”相比,“c”与“b”相比较, “c”与“c”比较。

python python-3.x list comparison nested-lists
3个回答
1
投票

为了将来参考,最好在代码中包含输入列表(a,b,c),而不是使用屏幕截图来保存必须输入整个列表的人。我用了一些较短的版本进行测试。

您可以执行以下操作来迭代两个列表并比较结果。这比使用for i in range(len(data_set)):更整洁

# Make some test data
a= ["ID_A", ['T', 'G', 'A']]
b= ["ID_B", ['T', 'C', 'A']]
c= ["ID_C", ['C', 'A', 'A']]

data = [a,b,c]

# entry1 takes each of the values a,b,c in order, and entry2 will do the same,
# so you'll have all possible combinations.
for entry1 in data:
    for entry2 in data:
        score = compare(entry1[1], entry2[1])
        print("Compare ", entry1[0], " to ", entry2[0], "Score :", round(score))

输出:

Compare  ID_A  to  ID_A  Score : 100
Compare  ID_A  to  ID_B  Score : 67
Compare  ID_A  to  ID_C  Score : 33
Compare  ID_B  to  ID_A  Score : 67
Compare  ID_B  to  ID_B  Score : 100
Compare  ID_B  to  ID_C  Score : 33
Compare  ID_C  to  ID_A  Score : 33
Compare  ID_C  to  ID_B  Score : 33
Compare  ID_C  to  ID_C  Score : 100

你可能最好将分数存储在与你保存列表的数组不同的数组中。


1
投票

只需使用第二个嵌套循环

for i in range(len(data_set)):
    for j in range(len(data_set)):
        data_set[i].append(compare(data_set[j][1], data_set[i][1]))
        print(round(data_set[i][2], 2), end=", ")

0
投票

您还可以使用itertools.combinations来比较所有子列表。此外,在您的compare()函数中,您可能需要考虑返回一个值,该值指示子列表不具有可比性,而不是引发异常,以便在比较更大的子列表集时不会过早地使循环短路。

以下是一个示例(还包括一个稍微简单的compare()函数版本,当列表由于长度而无法比较时返回-1,但不执行列表与自身的比较,因为在该情况下返回值始终为100并且似乎是一种性能浪费)。

import itertools

data_set = [
    ['AB12345',['T','T','C','C','A','C','A','G','C','T','T','T','T','C']],
    ['AB12346',['T','T','C','C','A','C','C','G','C','T','C','T','T','C']],
    ['AB12347',['T','G','C','C','A','C','G','G','C','T','T','C','T','C']]
    ]

def compare(a, b):
    length = len(a) if len(a) == len(b) else 0
    similarity = sum(1 for i in range(length) if a[i] == b[i])
    return similarity / length * 100 if length else -1

for a, b in itertools.combinations(data_set, 2):
    compared = a[0] + ' and ' + b[0]
    result = compare(a[1], b[1])
    print(f'{compared}: {result}')

# OUTPUT
# AB12345 and AB12346: 85.71428571428571
# AB12345 and AB12347: 78.57142857142857
# AB12346 and AB12347: 71.42857142857143
© www.soinside.com 2019 - 2024. All rights reserved.