在Python中使用frozenset作为一对数据。

8

我想要创建一对元素。我不关心元素的顺序,所以我使用了frozenset

我可以想到以下两种方法从frozenset中迭代出元素。有没有更高级的方法?谢谢。

pair = frozenset([element1, element2])
pair2 = list(pair)
elem1 = pair2[0]
elem2 = pair2[1]

pair = frozenset([element1, element2])
elems = []
for elem in pair:
    elems.append(elem)
elem1 = elems[0]
elem2 = elems[1]

看起来你已经在使用 for elem in pair 对元素进行迭代了,还有什么需要的吗? - senderle
当一对中的两个元素相同时,frozenset 也可能会令人困惑。这样就不会有一对了 - 我们将得到一个只包含单个元素的 frozenset,你的代码将因为 IndexError 而出错。 - arrakis_sun
4个回答

16
pair = frozenset([element1, element2])
elem1, elem2 = pair

这一定是他的意思。+1 - senderle
@kindall:+1 从未想过可以这样解包集合!顺便说一句:可能提到元组也同样有效率... - phooji
是的,我不确定为什么他不只是使用元组。但是解包可以与任何序列一起使用--实际上甚至可以与迭代器一起使用。 - kindall
1
元组保留顺序信息,而集合或不可变集合则不保留该信息。在我的问题中,(x, y) 和 (y, x) 都应该是相等的。 - Sangmin
是的,相等性是一个很好的理由。我会把它放在我的技巧袋里。 :-) - kindall
显示剩余3条评论

9

如果你有很多这些配对的东西,使用frozenset()不是个好主意。应该使用元组代替。

>>> import sys
>>> fs1 = frozenset([42, 666])
>>> fs2 = frozenset([666, 42])
>>> fs1 == fs2
True
>>> t1 = tuple(sorted([42, 666]))
>>> t2 = tuple(sorted([666, 42]))
>>> t1 == t2
True
>>> sys.getsizeof(fs1)
116
>>> sys.getsizeof(t1)
36
>>>

更新奖励:排序后的元组具有可预测的迭代顺序:

>>> for thing in fs1, fs2, t1, t2: print [x for x in thing]
...
[42, 666]
[666, 42]
[42, 666]
[42, 666]
>>>

更新2 ……它们的repr()是相同的:

>>> repr(fs1)
'frozenset([42, 666])'
>>> repr(fs2)
'frozenset([666, 42])' # possible source of confusion
>>> repr(t1)
'(42, 666)'
>>> repr(t2)
'(42, 666)'
>>>

1
由于元组是不可变的,您可以轻松创建一个在__init __()方法中排序的tuple子类。不错的技巧。 - kindall
1
实际上,它必须在__new __()中而不是__init __()中(因为元组是不可变的,在__init __()中不会初始化)。我刚试过了,效果很好。 - kindall
看起来是个很不错的技巧!但是,当我将这个技巧应用到我的代码中时,程序运行有点慢。(我不知道为什么。我想为我的代码创建一个代码片段并重新分析。我稍后会再发布另一件事情。)无论如何,非常感谢你!! - Sangmin
只是好奇,看到了这个答案,想知道为什么使用frozensets不是一个好主意。这只是因为它们占用了太多的内存吗? - Jordan Reiter
好的,明白了。由于原帖作者表示他不关心元素的顺序,我甚至没有想到可预测的顺序是一种特性。 - Jordan Reiter

1
如果只有两个元素,您可以将它们解除序列化。但我不确定您在这里尝试做什么与不可变集合。
>>> s = frozenset([1,2])
>>> s
frozenset({1, 2})
>>> x,y = s
>>> x
1
>>> y
2

0

针对上面的评论进行详细说明,假设您的元素容易排序,您可以使用以下代码将无序对类从tuple创建:

class Pair(tuple):
    def __new__(cls, seq=()):
        assert len(seq) == 2
        return tuple.__new__(tuple, sorted(seq))

然后你得到:

>>> Pair((0, 1))
(0, 1)

>>> Pair((1, 0))
(0, 1)

>>> Pair((0, 1)) == Pair((1, 0))
True

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接