合并两个集合并将其分成对
我需要把两组数据合成一组配对的结果(元组)。这个结果集只会有一种可能的配对,比如对于两组数据:1,2 和 3,4,结果应该是:((1, 3), (2, 4))。完整的练习内容可以在这里找到:http://pastebin.com/mUaKV4G7
我需要用 pop 方法来实现这个功能。到目前为止,我的代码是这样的:
def mating_pairs(males, females):
pairs = set()
tmp_males, tmp_females = males.copy(), females.copy()
for male in tmp_males:
for female in tmp_females:
pairs.add(males.pop())
pairs.add(females.pop())
zip(pairs[::2], pairs[1::2])
return pairs
这个函数在运行到以下部分时还挺正常的:
zip(pairs[::2], pairs[1::2])
但如果没有它,给定两组数据的话,它会把它们合在一起;但是当我尝试用 zip 来分成配对时,就出现了这个错误:
'set' object is not subscriptable
这让我觉得在某个地方返回了 None,而不是正确的结果。
这个函数需要同时处理整数和字符串(我觉得不需要按照特定顺序来配对值),而且两组数据的值数量是相等的。
有人能告诉我我哪里做错了吗?
4 个回答
我有点不太明白你想做什么。不过根据你发的代码,我猜测你是想把每个男性和每个女性配对一次,然后把每对组合放到一个最终的列表里。
如果是这样的话,你想做的其实就是创建一个笛卡尔积。Python有一个很方便的函数可以做到这一点:itertools.product
。你可以这样使用它:
def mating_pairs(males, females):
return set(itertools.product(males, females))
如果你想手动实现这个功能,可以用两个嵌套的for循环来获取所有组合。不过你现在的做法,使用了pop
,是行不通的。你在代码中做的是遍历所有男性和女性(在复制参数之后),然后从原始集合中弹出元素。这样的话,很快两个集合males
和females
就会变空,因为你在为每个可能的组合不断地从它们中弹出元素,而没有考虑到只有在重复使用单个元素的情况下,才能得到所有组合。
你可以这样修正你的代码,而不使用pop:
def mating_pairs(males, females):
pairs = set()
# We only iterate over the items, so we don’t modify the original sets.
for male in males:
for female in females:
# And instead of adding individual items by once, and zipping them
# later, we just directly add tuples to the set.
pairs.add((male, female))
return pairs
如果你一定要用pop方法,试着把males
和females
同时弹出,放到一个元组里,然后再把这个元组加到pairs
中(顺便说一下,我不太明白你为什么要复制你的集合并销毁原来的集合,不过我想你有你的理由)。另外,同时遍历males
和females
不会给你想要的结果——你应该在弹出元素时检查每个集合是否为空。你想要的结果更像这样:
def mating_pairs(males, females):
pairs = set()
tmp_males, tmp_females = males.copy(), females.copy()
while tmp_males and tmp_females:
pairs.add((tmp_males.pop(),tmp_females.pop()))
return pairs
不过如果能避免使用set.pop
,这会简单一些:
def mating_pairs(males, females):
return set(zip(males,females))
另外,请注意,除非你使用某种有序集合的数据类型,否则这不能算是完整的答案。因为这里使用的是set
,所以你不能保证保留传入的males
和females
的任何顺序。
这个错误告诉你发生了什么:pairs
是一个 set
(集合),而表达式 pairs[::2]
的意思是“每隔一个元素取一个”。问题在于,set
是没有固定顺序的,所以“每隔一个元素”这个说法就没有意义了。因为元素的顺序是无法确定的,所以 Python 报错,而不是随便给你一个顺序。
你可能想做的事情是,要么按照出现的顺序把男性和女性配对:
def mating_pairs(males, females):
return zip(males, females)
要么是把所有可能的男性和女性配对(就是两个列表的笛卡尔积):
from itertools import product
def mating_pairs(males, females):
return product(males, females)
看起来你的作业是要实现 zip
或者 product
功能 :-)