代码之家  ›  专栏  ›  技术社区  ›  Björn Pollex

Python中集合的迭代顺序

  •  17
  • Björn Pollex  · 技术社区  · 14 年前

    如果我有两个相同的集合,意思是 a == b 给了我 True ,它们的迭代顺序是否相同?我试过了,效果很好:

    >>> foo = set("abc")
    >>> bar = set("abc")
    >>> zip(foo, bar)
    [('a', 'a'), ('c', 'c'), ('b', 'b')]
    

    我的问题是,我是幸运的,还是这种行为有保证?

    5 回复  |  直到 14 年前
        1
  •  21
  •   Jason Orendorff Oliver    14 年前

    不是的 只是

    n = set("abc")
    print n
    
    m = set("kabc")
    m.remove("k")
    print m
    

    …您可以获得不同的订单:

    set(['a', 'c', 'b'])
    set(['a', 'b', 'c'])
    
        2
  •  4
  •   Cristian Ciupitu    14 年前

    你很幸运,订单不能保证。唯一可以保证的是,这些集合将具有相同的元素。

    zip(sorted(foo), sorted(bar)) .

        3
  •  4
  •   Katriel    14 年前

    不。:

    >>> class MyStr( str ):
    ...     def __hash__( self ):
    ...             return 0
    ...
    >>> a = MyStr( "a" )
    >>> b = MyStr( "b" )
    >>> c = MyStr( "c" )
    >>> foo = { a, b, c }
    >>> foo
    {'c', 'b', 'a'}
    >>> bar = { b, a, c }
    >>> foo is bar
    False
    >>> foo ==  bar
    True
    >>> list( zip( foo, bar ) )
    [('c', 'c'), ('b', 'a'), ('a', 'b')]
    

    另外,我不知道 __hash__ 超控是必要的。我只是试了些我认为可以打破这个的东西,它成功了。

        4
  •  1
  •   Steven Rumbalski    14 年前

    是的,你很幸运。参见示例:

    import random
    r = [random.randint(1,10000) for i in range(20)]
    foo = set(r)
    r.sort(key=lambda _: random.randint(1,10000))
    bar = set(r)
    print foo==bar
    print zip(foo, bar)
    

    结果是:

    True
    [(3234, 3234), (9393, 9393), (9361, 1097), (1097, 5994), (5994, 2044), (1614, 1614), (6074, 4377), (4377, 9361), (5202, 5202), (2355, 2355), (1012, 1012), (7349, 7349), (6198, 6198), (8489, 8489), (7929, 7929), (6556, 6074), (6971, 6971), (2044, 6556), (7133, 7133), (383, 383)]
    
        5
  •  0
  •   Gangadhar    14 年前

    我觉得你很幸运。不过,也可能是因为集合中的元素是相同的,所以它们的存储顺序是相同的。这种行为不是你想依赖的。