【问题标题】:Finding duplicated values in a dictionary and printing them only in case the values with the same keys are different在字典中查找重复值并仅在具有相同键的值不同时打印它们
【发布时间】:2018-08-23 12:52:26
【问题描述】:

我正在从 CSV 文件创建一个三元组字典,其中键 - 行号和值是一个包含三个整数的列表。我还在创建另一个字典(名称),其中键为行号,值为两个字符串的列表。我想找到包含相同三元组的所有行,以防名称对不同。

到目前为止,我的代码是查找所有重复项,以防两行存在相同的三元组值,但如果存在 3 行或更多行的重复,它将无法正常工作。我想更新或重新编写整个脚本,以便在 3 个或更多重复的情况下检查所有名称值是否不同并仅打印具有不同名称的行。例如,如果我们有以下三元组字典: triplet = {1: [111, 222, 333], 2: [111, 222, 333], 3: [111, 222, 333], }names = {1: ['name1', 'name2'], 2: ['name1', 'name2'], 3: ['name1', 'name3']} 这将导致创建另一个字典:duplicated_value_keys = {(111, 222, 333): [1, 2, 3]} 并且我的脚本不会显示重复,因为 names[1] == names[2] 但原则上它应该打印第 2 行和第 3 行上的三元组值具有不同的名称。

for csv_infile in os.listdir(input_dir):
        if csv_infile.lower().endswith('.csv'):
            csv_in = os.path.join(input_dir, csv_infile)
            with open(csv_in) as f_in:
                # Creating dictionaries containing as a key the line number and as a value
                triplet = {}
                names = {}
                l_num = 0
                for line in f_in:
                    l_num += 1
                    triplet[l_num] = [(line.split('\t')[1]), (line.split('\t')[2]), (line.split('\t')[3])]
                    names[l_num] = [(line.split('\t')[4].lower().strip()), (line.split('\t')[5].lower().strip())]

                # Finding the duplicated values and creating a new dictionary with values the line numbers.
                duplicated_value_keys = collections.defaultdict(list)
                for key, value in triplet.items():
                    duplicated_value_keys[tuple(value)].append(key)
                for duplicated_keys in duplicated_value_keys.values():
                    if len(duplicated_keys) >1 and names[duplicated_keys[0]] != names[duplicated_keys[1]]: 
                        print("There is a duplicated triplet on lines: {}.\n".format(', '.join(map(str, duplicated_keys))))            

[编辑]:CSV 输入文件具有以下格式,并且是制表符分隔的:

2       8004    3014    3       test name   1       14080   1       0       3478    1572    0       0
2       8004    3014    3       test name    1       8004    1       0       3478    1572    0       0
3       8004    3014    3       test name1   1       8004    1       0       3477    1571    0       0

【问题讨论】:

  • 目前还不清楚不同名称的含义。与第一个条目不同,每个条目都不同?如果与第一个条目不同,则只显示最后一个条目。
  • @MartinEvans,首先感谢您的帮助。使用不同的名称,我的意思是只有当第 4 列和第 5 列中的条目不同时,脚本才应显示重复的第 1、2、3 列的行。例如,在我的 CSV 示例中,应该只报告第 2 行和第 3 行,因为第 1 行和第 2 行的第 4 列和第 5 列是相同的。

标签: python python-3.x csv dictionary


【解决方案1】:

可以使用defaultdict(list) 来检测重复行。三元组将是字典的键,每个将包含一个行号列表和找到三元组的名称。读入所有条目后,遍历字典并仅显示那些包含不同名称的条目。例如:

import csv
from collections import defaultdict

triplets = defaultdict(list)

with open('test.csv', newline='') as f_input:
    csv_input = csv.reader(f_input, delimiter='\t')

    for line, row in enumerate(csv_input, start=1):
        triplets[tuple(row[1:4])].append((line, list(map(str.lower, row[4:6]))))

for triplet, entries in sorted(triplets.items()):
    if len(entries) > 1 and len({tuple(names) for line, names in entries}) > 1:
        print("Duplicate triplet: {} on lines:".format(triplet))
        for line, names in entries:
            print("  {}, {}, {}".format(line, *names))
        print()

对于给定的test.csv,这将产生:

Duplicate triplet: ('13115', '3209', '3') on lines:
  44, skylink, horor film
  69, skylink, private spice

Duplicate triplet: ('13139', '3219', '3') on lines:
  8, skylink, nova cinema
  13, skylink, prima zoom

Duplicate triplet: ('8004', '3014', '3') on lines:
  2, skylink, ct 2
  3, skylink, bar 2
  4, skylink, tst 22
  5, skylink, tst 22

【讨论】:

  • 但在这里我看不到名称是否唯一的检查。我的脚本已经在输出重复的三元组,然后我正在运行if len(duplicated_keys) >1 and names[duplicated_keys[0]] != names[duplicated_keys[1]]:,但这只是检查前两次出现。
  • 您的示例的预期输出是什么?
  • Duplicate triplet: ('8004', '3014', '3') on lines: 2, 3 因为第 1 行和第 2 行具有相同的 ('test', 'name') 而只有第 3 行具有不同的 ('test', 'name1')
  • 如果重复行的组合(第 4 列和第 5 列)不同,我的脚本应该返回三重列 1 到 3(从 0 开始计数)的行数。如果重复行的第 4 列和第 5 列相同,则不应报告重复。
  • 你可以在前面添加row = list(map(str.strip, row))
猜你喜欢
  • 2021-04-17
  • 1970-01-01
  • 2020-12-18
  • 1970-01-01
  • 2011-11-02
  • 2016-01-19
  • 2021-08-17
  • 1970-01-01
  • 2021-12-11
相关资源
最近更新 更多