Python Uniquify仅基于索引的一个值的元组列表

时间:2014-11-04 03:50:56

标签: python list python-3.x tuples

我发誓我首先搜索了SO,发现了许多“可以工作 - 如果适应”,但没有什么真正帮助我。我所拥有的是一个元组列表:

[('', 'noreply@bookfresh.com'), ('Andrea', 'andrea@aaa.com'), ('Your Book', 'noreply@bookfresh.com'), ..]

在这种情况下,它是一个元组列表,在所有索引中都有一个“Name”作为第一个值,“Email”作为第二个值。并且列表没有以任何特定方式排序(尚未)。

我需要的是一个干净且易于理解(我不一定在寻找我甚至无法阅读的单行)的方式来制作一个“未加工的”列表,但是有这些规则/警告:

  • 只有在找到元组的第二个值的副本时才删除元组(在这种情况下,它恰好是一个电子邮件地址,它将是“noreply@bookfresh.com”)
  • 不要删除重复元组的所有实例。我需要保留一个,并且要保留的那个应该是具有第一个对象的len()最多的元组。 (在这种情况下,在重复的元组中,它只保留元组('Your Book','noreply @ bookfresh.com')。

此最小化示例中的最终输出将是:

[('Andrea', 'andrea@aaa.com'), ('Your Book', 'noreply@bookfresh.com'), ..]

如果输出没有排序或排序并不重要,因为我知道如何排序未排序的元组列表。感谢

3 个答案:

答案 0 :(得分:2)

方法#1:收集所有名称

如果我们想要最易理解的版本,而不是最简单的版本,可能就像

pairs = [('', 'noreply@bookfresh.com'), ('Andrea', 'andrea@aaa.com'), ('Your Book', 'noreply@bookfresh.com')]

data = {}
for name, email in pairs:
    if email not in data:
        data[email] = []
    data[email].append(name)

output = [(email, max(data[email], key=len)) for email in data]

会奏效。这将问题分为两部分:构建以电子邮件地址为键的字典,以及可能的名称列表作为值;并循环遍历所有电子邮件地址并获得最长的名称。

第一部分可以使用setdefault来压缩,例如

for name, email in pairs:
    data.setdefault(email, []).append(name)

但不是每个人都熟悉它。


方法#2:排序并制作唯一

或者,我们可以一次按电子邮件和名称长度排序,然后从中创建一个字典,只保留最后一个键/值对:

>>> pairs.sort(key=lambda x: (x[1], len(x[0])))
>>> data = {v: k for k,v in pairs}
>>> [(v,k) for k,v in data.items()]
[('Andrea', 'andrea@aaa.com'), ('Your Book', 'noreply@bookfresh.com')]

答案 1 :(得分:1)

您可以使用第二个条目作为关键字来构建字典。字典具有在其键中不包含任何重复的适当性。如果您在构建字典之前按第一个元素的长度排序,它将为您提供所需的内容:

your_list_sorted = sorted(your_list, key=lambda x: len(x[0]))
out = dict((v, k) for k, v in your_list_sorted)

如果您需要以列表形式输出,可以out_list = list(out.items())来获取它。

答案 2 :(得分:0)

可能最简单的方法是使用这样的集合:

L = [('', 'noreply@bookfresh.com'), ('Andrea', 'andrea@aaa.com'), ('Your Book', 'noreply@bookfresh.com'), ..]

emails = set()

result_L = []

for item in L:
    if item[1] in emails:
        # this email address is already seen
        continue

    result_L += [item]
    emails.add(item[1])

但是,如果你想保留最后一项,你可以使用它(最后,你可能想要反转result_L):

for i in reversed(L):
    # ...

还有很多其他方法可以做到这一点。例如,请考虑使用dict

result_dict = {}

for item in L:
    result_dict[item[1]] = item[0]

result_L = [(y, x) for (x, y) in result_dict.items()]