合并两个集合并将其分成对

0 投票
4 回答
904 浏览
提问于 2025-04-17 07:08

我需要把两组数据合成一组配对的结果(元组)。这个结果集只会有一种可能的配对,比如对于两组数据: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 个回答

0

我有点不太明白你想做什么。不过根据你发的代码,我猜测你是想把每个男性和每个女性配对一次,然后把每对组合放到一个最终的列表里。

如果是这样的话,你想做的其实就是创建一个笛卡尔积。Python有一个很方便的函数可以做到这一点:itertools.product。你可以这样使用它:

def mating_pairs(males, females):
    return set(itertools.product(males, females))

如果你想手动实现这个功能,可以用两个嵌套的for循环来获取所有组合。不过你现在的做法,使用了pop,是行不通的。你在代码中做的是遍历所有男性和女性(在复制参数之后),然后从原始集合中弹出元素。这样的话,很快两个集合malesfemales就会变空,因为你在为每个可能的组合不断地从它们中弹出元素,而没有考虑到只有在重复使用单个元素的情况下,才能得到所有组合。

你可以这样修正你的代码,而不使用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
1

如果你一定要用pop方法,试着把malesfemales同时弹出,放到一个元组里,然后再把这个元组加到pairs中(顺便说一下,我不太明白你为什么要复制你的集合并销毁原来的集合,不过我想你有你的理由)。另外,同时遍历malesfemales不会给你想要的结果——你应该在弹出元素时检查每个集合是否为空。你想要的结果更像这样:

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,所以你不能保证保留传入的malesfemales的任何顺序

2

这个错误告诉你发生了什么: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 功能 :-)

撰写回答