比较两个不匹配的列表,并标识具有最大匹配元素的行

时间:2018-11-22 17:15:54

标签: python python-3.x

背景

我有两个列表(列表),每个列表都是通过从两个地址表中读取数据而创建的。

每行的第一个元素是列表行的唯一标识符,其余元素用于地址比较。

每个列表如下所示:

列表1(cli添加)

['3', 'V8T5G2', 'VICTORIA', 'BR', 'CANADA']
['543', '234', '654', 'BELMONT', 'AVENUE', 'V8S3T4', 'VICTORIA', 'BR', 'CANADA']    
['28', '70', 'RUSHTON', 'RD', 'M6C2X8', 'YK', 'ON', 'CANADA']

清单2(结构添加)

['7H0044', '234', '654', 'BELMONT', 'AVENUE', 'V8S3T4', 'VICTORIA', 'BC', 'CANADA']
['7H0033', 'V8T5G2', 'VICTORIA', 'BC', 'CANADA']
['7H0001', '700', 'RUSHTON', 'ROAD', 'M6C2X7', 'YORK', 'ON', 'CANADA']
['7H0034', '217', 'BONNYMUIR', 'DRIVE', 'V7S1L4', 'WEST', 'VANCOUVER', 'BC', 'CANADA']

任务目标 我的任务是将测试列表中的地址与另一个列表进行比较,并标记所有匹配和不匹配的记录。

我逐一遍历列表1中的每一行,并与列表2的每一行进行逐元素比较。如果在列表2的任何行中找到了从列表1的行拉出的所有元素,则将该记录标记为“匹配”,并保留列表2的行。已经能够识别出完全匹配的记录。

问题点 真正的挑战是关于不匹配的行。对于列表1中不匹配的记录,我想确定列表2中最匹配的行。如果列表1的行在列表2的三行中有匹配的元素,我想选择匹配元素数最多的列表2的行。

预期结果 在上面共享的数据中,从列表1开始,第二行(id 542)具有完全匹配。但是其他两个记录并没有完全匹配。

我希望能够创建不匹配记录的列表并捕获不匹配的元素:

[[comparison record from list 1],[Most matching record from list 2],[non-matching elements from list 1]]

因此,对于上述共享数据,我需要一个新列表(列表),看起来像这样:

[['3', 'V8T5G2', 'VICTORIA', 'BR', 'CANADA'],['7H0033', 'V8T5G2', 'VICTORIA', 'BC', 'CANADA'],['BR']]
[['28', '70', 'RUSHTON', 'RD', 'M6C2X8', 'YK', 'ON', 'CANADA'],['7H0001', '700', 'RUSHTON', 'ROAD', 'M6C2X7', 'YORK', 'ON', 'CANADA'],['70','RD','M6C2X8', 'YK']]

以下代码部分地为我提供了结果。我无法找到一种方法来过滤匹配度最高的行。

代码段 这是我找到匹配记录和不匹配记录的方式(列表1由cli_add_fnl引用,列表2是struc_add_fnl)。还想出了列出不匹配元素和匹配元素计数的方法。只需要一种方法就只提取列表元素1的最大计数行。

### Step 4 - Identifying the matching and non matching addresses ###  
validated_addresses_all = []
invalid_addresses_all = []

for cli_add in cli_add_fnl:            
    comparison_cli_add=cli_add.copy()

    #removing the id column from comparison
    comparison_cli_add.pop(0)


    for struct_add in struct_add_fnl:
        matching_elements = [address_element for address_element in comparison_cli_add if address_element in struct_add]

        #capture the matching records
        if matching_elements == comparison_cli_add:
            validated_addresses_all.append(cli_add)
        else:
            invalid_addresses_all.append(cli_add)
            invalid_addresses_all.append(struct_add)
            invalid_addresses_all.append(len(set(comparison_cli_add) & set(struct_add)))
            invalid_addresses_all.append(nonmatching_elements)

#remove the duplicate entries
fnl_validated_addresses = [] 
for add in validated_addresses_all: 
    if add not in fnl_validated_addresses: 
        fnl_validated_addresses.append(add)

1 个答案:

答案 0 :(得分:1)

这是通过比较func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier:SelectedItemCell.identifier, for: indexPath) as! SelectedItemCell cell.delegate = self return cell } extension PrescriptionVC: SelectedItemCellDelegate { func deleteButtonDidTapped(_ cell: SelectedItemCell) { // Need tableview indexPath as well SelectedItemCell indexPath. } } adds中的值并在内部保留最高匹配数的计数器来忽略位置和第一项的一种方法。只要存在匹配项,它将更新计数器并获得最高匹配项的索引,否则在下面的示例中,它什么也不做。然后比较与struct_adds中的项目差异和匹配度最高的匹配项。

然后将结果相应地添加到列表中。

add

或者,如果您想使用adds = [['3', 'V8T5G2', 'VICTORIA', 'BR', 'CANADA'], ['543', '234', '654', 'BELMONT', 'AVENUE', 'V8S3T4', 'VICTORIA', 'BR', 'CANADA'], ['28', '70', 'RUSHTON', 'RD', 'M6C2X8', 'YK', 'ON', 'CANADA']] struct_adds = [ ['7H0044', '234', '654', 'BELMONT', 'AVENUE', 'V8S3T4', 'VICTORIA', 'BC', 'CANADA'], ['7H0033', 'V8T5G2', 'VICTORIA', 'BC', 'CANADA'], ['7H0001', '700', 'RUSHTON', 'ROAD', 'M6C2X7', 'YORK', 'ON', 'CANADA'], ['7H0034', '217', 'BONNYMUIR', 'DRIVE', 'V7S1L4', 'WEST', 'VANCOUVER', 'BC', 'CANADA']] results = [] for add in adds: match_count = 0 match_index = 0 for idx,struct_add in enumerate(struct_adds): matches = [add_item in struct_add[1:] for add_item in add[1:]] if matches.count(True) > match_count: match_count = matches.count(True) match_index = idx if match_count == 0: pass # no matches else: highest_match = struct_adds[match_index] differences = [i for i in add[1:] if i not in highest_match] results.append([add,highest_match,differences]) 操作(如注释中所建议的那样更有效),可以将set块替换为:

for

两者的结果相同:

for add in adds:
    match_count = 0
    match_index = 0
    for idx,struct_add in enumerate(struct_adds):
        matches = set(add[1:]) & set(struct_add[1:])
        if len(matches) > match_count:
            match_count = len(matches)
            match_index = idx
    if match_count == 0:
        pass # no matches
    else:
        highest_match = struct_adds[match_index]
        differences = list(set(add[1:]) - set(highest_match[1:]))
        results.append([add,highest_match,differences])

在此示例中,我还应该补充一点,也不要使事情变得更加复杂,它将采用第一最高匹配。此部分在results >> [[['3', 'V8T5G2', 'VICTORIA', 'BR', 'CANADA'], ['7H0033', 'V8T5G2', 'VICTORIA', 'BC', 'CANADA'], ['BR']], [['543', '234', '654', 'BELMONT', 'AVENUE', 'V8S3T4', 'VICTORIA', 'BR', 'CANADA'], ['7H0044', '234', '654', 'BELMONT', 'AVENUE', 'V8S3T4', 'VICTORIA', 'BC', 'CANADA'], ['BR']], [['28', '70', 'RUSHTON', 'RD', 'M6C2X8', 'YK', 'ON', 'CANADA'], ['7H0001', '700', 'RUSHTON', 'ROAD', 'M6C2X7', 'YORK', 'ON', 'CANADA'], ['70', 'RD', 'M6C2X8', 'YK']]] 子句中进行管理,比较真实匹配数必须大于当前匹配数。