list(set()) 没有给我想要的列表顺序



我有这样的list of dicts

a = [{'key1':val, 'key2':val, 'key3':val},{'key1':val, 'key2':val, 'key3':val}]

我正在尝试将键从值获取到一个列表,如下所示:

a = ['key1', 'key2', 'key3']

使用此代码

key_list = set().union(*(b.keys() for b in a))
key_list = list(key_list)
>>> ['key2', 'key1', 'key3']

这行得通,但值的顺序不一样,是因为我将数据插入到set吗?如何使用相同的值(键(顺序进行?

核心问题

套装不会记住广告顺序。 他们倾向于根据底层的hash((函数对数据进行加扰。

要记住顺序,请考虑使用列表或 OrderedDict。

使用由集合支持的列表的解决方案

>>> a = [{'key1':1, 'key2':2, 'key3':3},{'key1':4, 'key2':5, 'key3':6}]
>>> key_list = []
>>> seen = set()
>>> for d in a:
for k in d:
if k not in seen:
seen.add(k)
key_list.append(k)
>>> key_list
['key1', 'key2', 'key3']

这使用名为key_list的列表来记住顺序,并使用名为seen的集合来跟踪是否已看到键。

使用 OrderedDict 的解决方案

这种方法较短,但有点花哨:

>>> from collections import OrderedDict
>>> from itertools import chain
>>> list(OrderedDict.fromkeys(chain.from_iterable(a)))
['key1', 'key2', 'key3']

这使用chain.from_iterable((将输入平展为单个键字符串。 然后,OrderedDict.fromkeys((将它们组合成字典,同时记住顺序并消除重复项。 最后,list((将结果转换为所需的列表。

只需自己构建列表即可。 例如

lst = []
# Loop through all dictionaries
for dct in a:
# Loop through all keys of the current dictionary
for key in dct.keys():
# If the key is already in the list, skip it
if key in lst:
continue
# Append the key to the list
lst.append(key)
print(lst) # ['key1', 'key2', 'key3']

如果我理解您的意图,您需要字典的唯一键的有序列表。您当前的方法存在一个问题:从集合返回的值不一定与它们的添加顺序相同。我想说你的方法几乎就在那里。您现在需要做的就是对列表进行排序,这将保证顺序。

key_list = set().union(*(b.keys() for b in a))
key_list = sorted(list(key_list))
>>> ['key1', 'key2', 'key3']

更新:由于您似乎希望它们按照a中的顺序显示,我们还有更多工作要做:

reference = set(a[0].keys())
key_list = list(a[0].keys())
for d in a[1:]:
newkeys := [k in d.keys() if check_n_add(k, reference)]
key_list.extend(newkeys)
func check_n_add(s, k):
if k not in s:
s.add(k)
return True
return False

即使键尚未排序,这也应该保持顺序。

set 对象是可哈希对象的无序集合。它不维护给定数据的顺序。一个可能的答案可能是使用列表理解来完成的。

d = []
[ d.append(c) for b in a for c in b.keys() if c not in d]
>>> d
# ['key1', 'key2', 'key3']

最新更新