将列表转换为集合会更改元素顺序

新手上路,请多包涵

最近我注意到,当我将 list 转换为 set 时,元素的顺序发生了变化并按字符排序。

考虑这个例子:

 x=[1,2,20,6,210]
print(x)
# [1, 2, 20, 6, 210] # the order is same as initial order

set(x)
# set([1, 2, 20, 210, 6]) # in the set(x) output order is sorted

我的问题是 -

  1. 为什么会这样?
  2. 如何在不丢失初始顺序的情况下进行设置操作(尤其是设置差异)?

原文由 d.putto 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.5k
2 个回答
  1. A set 是一个无序数据结构,所以它不保留插入顺序。

  2. 这取决于您的要求。如果你有一个普通的列表,并且想在保留列表顺序的同时删除一些元素集,你可以使用列表理解来做到这一点:

    >>> a = [1, 2, 20, 6, 210]
   >>> b = set([6, 20, 1])
   >>> [x for x in a if x not in b]
   [2, 210]

如果你需要一个既支持 快速成员资格测试 又支持 插入顺序保存的 数据结构,你可以使用 Python 字典的键,从 Python 3.7 开始保证保存插入顺序:

    >>> a = dict.fromkeys([1, 2, 20, 6, 210])
   >>> b = dict.fromkeys([6, 20, 1])
   >>> dict.fromkeys(x for x in a if x not in b)
   {2: None, 210: None}

b 真的不需要在这里订购——你也可以使用 set 。请注意, a.keys() - b.keys() 将设置差异返回为 set ,因此它不会保留插入顺序。

在旧版本的 Python 中,您可以使用 collections.OrderedDict 代替:

    >>> a = collections.OrderedDict.fromkeys([1, 2, 20, 6, 210])
   >>> b = collections.OrderedDict.fromkeys([6, 20, 1])
   >>> collections.OrderedDict.fromkeys(x for x in a if x not in b)
   OrderedDict([(2, None), (210, None)])

原文由 Sven Marnach 发布,翻译遵循 CC BY-SA 4.0 许可协议

在 Python 3.6 中, set() 现在 应该 保持顺序,但是对于 Python 2 和 3 还有另一种解决方案:

 >>> x = [1, 2, 20, 6, 210]
>>> sorted(set(x), key=x.index)
[1, 2, 20, 6, 210]

原文由 Tiger-222 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题