从(元组的元组)中删除重复项

时间:2018-10-24 18:43:25

标签: python python-3.x duplicates tuples

input_tuple = (
    (12805,'MLB','NAME1','body NAME1 Noah dev'),         
    (12805,'MLB','NAME2','body NAME2 Noah dev'),
    (12805,'MLB','NAME3','body NAME3 Elijah'),

    (12806,'MLB','NAME4','body NAME4 Liam sev'),
    (12806,'MLB','NAME5','body NAME5 Noah dev'),

    (12807,'MLB','NAME6','body NAME6 Liam sev'),
    (12807,'MLB','NAME7','body NAME7 epic peterson'),

    (12808,'MLB','NAME8','body NAME8 Liam sev'),
    (12808,'MLB','NAME9','body NAME9 epic peterson')         

    )

请考虑input_tuple中的第一位数字是关键,我们需要检查[3]索引上的重复数字,但请跳过前两个字符。

下面是我们需要看的两种情况:-

1)自我重复检查:现在,如果在第3个索引上发现任何重复,我们需要删除该行

2)跨重复项:检查完自我重复项后,我们需要对重复项进行检查,如果发现任何问题,则需要用首次出现的项替换

3)成对重复:在这种情况下,我想对重复进行检查,但仅当存在对重复时才应进行检查。我最后在input_tuple中进行了编辑:例如:

    (12808,'MLB','NAME8','body NAME8 Liam sev'),
    (12808,'MLB','NAME9','body NAME9 epic peterson') 

因为其重复项如下:

(12807,'MLB','NAME6','body NAME6 Liam sev'),
(12807,'MLB','NAME7','body NAME7 epic peterson'),

因此,也应将其消除。

output_tuple = (
    (12805,'MLB','NAME1','body NAME1 Noah dev'),
    (12805,'MLB','NAME3','body NAME3 Elijah dev'),

    (12806,'MLB','NAME4','body NAME4 Liam sev'),
    (12806,'MLB','NAME1','body NAME1 Noah dev'),

    (12807,'MLB','NAME4','body NAME4 Liam sev'),
    (12807,'MLB','NAME7','body NAME7 epic peterson')
    )

我尝试过的代码:(在第一种情况下工作正常)

def skip_two_words(str):
    str = ' '.join(str.split(' ')[2:])
    return str

input_tuple = (tuple({(x[0], skip_two_words(x[3])): x for x in 
input_tuple[::-1]}.values())[::-1])

    id_name_dict = defaultdict(list)
    for id, _, _, name in input_tuple:
        id_name_dict[id].append(name)
    seen = set()
    ignore_id_set = set()
    for _id, _namelst in id_name_dict.items():
            id = tuple(sorted(_namelst))
            if id not in seen:
                seen.add(id)
            else:
                ignore_id_set.add(_id)  # duplicate
    del id_name_dict, seen  # id_name_dict,seen are now eligible for garbage 
    collection
    output_tuple = tuple(item for item in input_tuple if item[0] not in 
    ignore_id_set)

1 个答案:

答案 0 :(得分:1)

无需重新发明轮子来放置重复项。 itertools文档有一个unique_everseen recipe,也可以通过more_itertools.unique_everseentoolz.unique在第三方库中使用。第二部分有点混乱,但是您可以使用自定义函数定义拆分,然后使用元组理解。

from toolz import unique

# drop duplicates
res = tuple(unique(input_tuple, key=lambda x: (x[0], tuple(x[-1].split()[2:]))))

# make mapping dictionary
d = {' '.join(tup[-1].split()[2:]): tup[-2] for tup in reversed(input_tuple)}

# apply dictionary mapping with some splits
def return_tup(tup, d):
    num, cat, name_id, full = tup
    full_split = full.split()
    name_words = ' '.join(full_split[2:])
    name_id = d[name_words]
    full = ' '.join([full_split[0], name_id, name_words])
    return num, cat, name_id, full

res = tuple(return_tup(tup, d) for tup in res)

((12805, 'MLB', 'NAME1', 'body NAME1 Noah dev'),
 (12805, 'MLB', 'NAME3', 'body NAME3 Elijah'),
 (12806, 'MLB', 'NAME4', 'body NAME4 Liam sev'),
 (12806, 'MLB', 'NAME1', 'body NAME1 Noah dev'),
 (12807, 'MLB', 'NAME4', 'body NAME4 Liam sev'),
 (12807, 'MLB', 'NAME7', 'body NAME7 epic peterson'))