使用一个子字典的值来对所有子字典进行排序

4

我有如下数据结构,希望将所有子字典按照 'order' 列的值进行排序。

输入:

to_sort = [
('Fruits', 
    {
    'size': {1:[4, 2, 7,9]}, 
    'name': {1:['Orange', 'Apple', 'Kiwi', 'Mango']},
    'color': {1:['Orange', 'Red', 'Brown','Green']},
    'order': {1:[2, 1, 4,3]}
    }
)
]

输出:

[
('Fruits', 
    {
    'size': {1:[2, 4, 9, 7]}, 
    'name': {1:['Apple', 'Orange', 'Mango', 'Kiwi']},
    'color':{1:['Red', 'Orange', 'Green', 'Brown']},
    'order':{1:[1, 2, 3, 4]}
    }
)
]

我尝试使用lambda函数

sort = to_sort[1]
print(sorted(sort.items(), key=lambda i: i['order'].values()))

我遇到了“tuple indices must be integers or slices, not str”错误。

2
字典中的每个项目为什么都是一个带有单个列表的字典?它们是否可以只是列表而不是字典? - FamousJameous
是的,你想做的是可能的,但有点麻烦。我知道这并不总是可能的,但我会重新考虑你的数据结构...就像FamousJameous指出的那样,为什么比如size不能简单地有一个值为[2, 4, 9, 7] - juanpa.arrivillaga
这不是一个有效的字典。你能修复它吗? - ayhan
1
@ayhan,我知道你迫不及待地想把它放入一个DataFrame中... - juanpa.arrivillaga
@juanpa.arrivillaga 谢谢 - Sandy
显示剩余5条评论
2个回答

1
假设您同意根据评论中提到的修改数据结构,这将对您起作用。这是从另一个问题改编而来:按另一个列表中的值排序列表?
to_sort = [('Fruits', {
    'size': [4, 2, 7,9],
    'name': ['Orange', 'Apple', 'Kiwi', 'Mango'],
    'color': ['Orange', 'Red', 'Brown','Green'],
    'order': [2, 1, 4,3]
    })
]

postsort = []
for category, catdata in to_sort:
    sorteddata = {}
    for name, namedata in catdata.iteritems():
        sorteddata[name] = [x for (y,x) in sorted(zip(catdata['order'], namedata))]
    postsort.append((category, sorteddata))
print postsort

这将导致:
[(
    'Fruits',
    {
        'color': ['Red', 'Orange', 'Green', 'Brown'],
        'size': [2, 4, 9, 7],
        'order': [1, 2, 3, 4],
        'name': ['Apple', 'Orange', 'Mango', 'Kiwi']
    }
)]

如果可能的话,我建议对您现有的数据结构进行修改以使其与此代码兼容。


1

如何处理已有的数据结构

您现有的数据结构有些混乱,但是以下是我处理它的方法(编辑假设颜色列表的键为123):

>>> to_sort = [
... ('Fruits', 
...     {
...     'size': {1:[4, 2, 7,9]}, 
...     'name': {1:['Orange', 'Apple', 'Kiwi', 'Mango']},
...     'color': {123:['Orange', 'Red', 'Brown','Green']},
...     'order': {1:[2, 1, 4,3]}
...     }
... )
... ]
>>> d = to_sort[0][1]
>>> keys = list(d.keys())
>>> idx = keys.index('order')
>>> ordered_kv = zip(keys, zip(*sorted(zip(*(d[k][n] for k in keys for n in d[k])), key = lambda t:t[idx])))
>>> sorted_dict = {k:{n:list(v) for n in d[k]} for k,v in ordered_kv}
>>> from pprint import pprint
>>> pprint(sorted_dict)
{'color': {123: ['Red', 'Orange', 'Green', 'Brown']},
 'name': {1: ['Apple', 'Orange', 'Mango', 'Kiwi']},
 'order': {1: [1, 2, 3, 4]},
 'size': {1: [2, 4, 9, 7]}}

让我们来分解一下:首先,我创建了一个键的规范列表,并找到了'order'的索引:

>>> keys = list(to_sort[0][1].keys())
>>> idx = keys.index('order')

下一步是将内部列表合并成元组,其中每个项目共享相同的相对位置:

zip

>>> list(zip(*(d[k][n] for k in keys for n in d[k])))
[(4, 2, 'Orange', 'Orange'), (2, 1, 'Red', 'Apple'), (7, 4, 'Brown', 'Kiwi'), (9, 3, 'Green', 'Mango')]

现在可以根据 idx 位置进行排序,然后 "解压缩" (实际上只是再次应用 zip-splat 组合):
>>> list(zip(*sorted(zip(*(d[k][n] for k in keys for n in d[k])), key=lambda t:t[idx])))
[(2, 4, 9, 7), (1, 2, 3, 4), ('Red', 'Orange', 'Green', 'Brown'), ('Apple', 'Orange', 'Mango', 'Kiwi')]

最后,你可以使用字典推导式重建你的疯狂字典,并确保将有序值与原始键一起压缩:
>>> ordered_kv = zip(keys, zip(*sorted(zip(*(d[k][n] for k in keys for n in d[k])), key = lambda t:t[idx])))
>>> sorted_dict = {k:{n:list(v) for n in d[k]} for k,v in ordered_kv}
>>> from pprint import pprint
>>> pprint(sorted_dict)
{'color': {123: ['Red', 'Orange', 'Green', 'Brown']},
 'name': {1: ['Apple', 'Orange', 'Mango', 'Kiwi']},
 'order': {1: [1, 2, 3, 4]},
 'size': {1: [2, 4, 9, 7]}}

然而...

在处理此类数据时,您真的应该考虑使用pandas库。请注意:

>>> import pandas as pd
>>> df = pd.DataFrame({k: pd.Series(v[1]) for k,v in to_sort[0][1].items()})
>>> df
    color    name  order  size
0  Orange  Orange      2     4
1     Red   Apple      1     2
2   Brown    Kiwi      4     7
3   Green   Mango      3     9

请注意,我仍然需要将您的原始数据结构调整为 pandas 数据框架,但如果您一开始就使用 DataFrame 进行操作,所有事情都会变得更加容易。现在,您可以做一些很酷的事情,比如:
>>> df.sort_values('order')
    color    name  order  size
1     Red   Apple      1     2
0  Orange  Orange      2     4
3   Green   Mango      3     9
2   Brown    Kiwi      4     7

有一个问题。在这种情况下,"{'color': {1: "可以是"{'color': {12:"或"{'color': {123:",因此sorted_values = zip(sorted(zip((to_sort[0][1][k][1]将无法工作。我们必须替换整个值sorted_values = zip(sorted(zip((to_sort[0][1][k]["value"]。你有什么想法如何做到这一点? - Sandy

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