python元组读取到列表_在Python中获取几个元组列表的第二个元素的简单有效方法?...

我是

Python的新手(在2.7中工作),我发现它是一个非常有价值的资源!

假设我正在处理几个通常具有形式(ID,值)的2元素元组的列表,例如,

list1 = [(111, 222), (111, 333), (111, 444)]

list2 = [(555, 333), (555, 444), (555, 777)]

list3 = [(123, 444), (123, 888), (123, 999)]

我真正想要做的是找到一种简单(并且计算效率)的方法来获得这些元组的第二个元素的交集.我已经查看了Python docs并发现集合可能会做我想要的…而this post有助于我理解如何获得两个列表的交集.

我知道我可以通过像这样循环遍历元组来创建三个全新的“仅值”列表:

newList1 = []

for tuple in list1:

newList1.append(tuple[1])

newList2 = []

for tuple in list2:

newList2.append(tuple[1])

newList3 = []

for tuple in list3:

newList3.append(tuple[1])

然后像这样得到每对的交集:

i_of_1and2 = set(newList1).intersection(newList2)

i_of_1and3 = set(newList2).intersection(newList3)

i_of_2and3 = set(newList1).intersection(newList3)

但是我的列表有点大 – 就像成千上万(有时数千万)的元组一样.这真的是获得这三个列表元组中第二个元素交集的最佳方法吗?对我来说似乎……不优雅……

谢谢你的帮助!

最佳答案 你显示一个大问题,开始使用variable1通常是一个不好的标志 – 如果你想拥有多个值,使用数据结构,而不是许多带编号名称的变量.这会阻止您反复重复代码,并有助于阻止错误.

让我们使用列表列表:

values = [

[(111, 222), (111, 333), (111, 444)],

[(555, 333), (555, 444), (555, 777)],

[(123, 444), (123, 888), (123, 999)]

]

现在我们想要只获得子列表中每个元组的第二个元素.这很容易使用list comprehension进行计算:

>>> [[item[1] for item in sublist] for sublist in values]

[[222, 333, 444], [333, 444, 777], [444, 888, 999]]

然后,我们想要项目之间的交叉点,我们使用itertools.combinations()来获得两对可能的对:

>>> for values, more_values in itertools.combinations(new_values, 2):

... set(values).intersection(more_values)

...

{444, 333}

{444}

{444}

所以,如果我们将它们包装在一起:

import itertools

values = [

[(111, 222), (111, 333), (111, 444)],

[(555, 333), (555, 444), (555, 777)],

[(123, 444), (123, 888), (123, 999)]

]

sets_of_first_items = ({item[1] for item in sublist} for sublist in values)

for values, more_values in itertools.combinations(sets_of_first_items, 2):

print(values.intersection(more_values))

这给了我们:

{444, 333}

{444}

{444}

我在这里做的改变是让内部列表成为一个集合理解,避免创建一个列表只是为了将它变成一个集合,并使用生成器表达式而不是列表理解,因为它被懒惰地评估.

最后要注意的是,如果你想要我们用来生成交集的列表的索引,那么使用the enumerate() builtin很简单:

sets_of_first_items = ({item[1] for item in sublist} for sublist in values)

for (first_number, first_values), (second_number, second_values) in itertools.combinations(enumerate(sets_of_first_items), 2):

print("Intersection of {0} and {1}: {2}".format(first_number, second_number, first_values.intersection(second_values)))

这给了我们:

Intersection of 0 and 1: {444, 333}

Intersection of 0 and 2: {444}

Intersection of 1 and 2: {444}

编辑:

在noted by tonyl7126,这也是一个通过使用更好的数据结构可以大大帮助的问题.这里最好的选择是将用户ID的dict用于一组产品ID.当您只需要一个集合时,没有理由将您的数据存储为列表,并且稍后将其转换为集合,并且dict对于您尝试存储的数据类型来说是一个更好的解决方案.

请参阅以下示例:

import itertools

values = {

"111": {222, 333, 444},

"555": {333, 444, 777},

"123": {444, 888, 999}

}

for (first_user, first_values), (second_user, second_values) in itertools.combinations(values.items(), 2):

print("Intersection of {0} and {1}: {2}".format(first_user, second_user, first_values.intersection(second_values)))

给我们:

Intersection of 555 and 123: {444}

Intersection of 555 and 111: {444, 333}

Intersection of 123 and 111: {444}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值