Py学习  »  Python

python高效的字典中的并行列表排序

LBaelish • 5 年前 • 843 次点击  

标题基本上说明了一切,我正在寻找一个有效的平行列表字典排序。

unsorted_my_dict = {
   'key_one': [1,6,2,3],
   'key_two': [4,1,9,7],
   'key_three': [1,2,4,3],
   ...
}
sorted_my_dict = {
   'key_one': [1,6,3,2],
   'key_two': [4,1,7,9],
   'key_three': [1,2,3,4],
   ...
}

我想分类 key_three 和字典中的所有其他列表并行。有几个类似的问题,但我正在努力,因为我在字典中有未知数量的键要排序,而且我只知道要排序的键的名称。( 密钥3 )

希望用普通的Python来实现这一点,不依赖第三方。

编辑1: 并行是什么意思?我的意思是如果我排序 密钥3 ,这需要交换最后两个值,字典中的所有其他列表也将交换最后两个值。

编辑2:python 3.4

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/30408
 
843 次点击  
文章 [ 3 ]  |  最新文章 5 年前
mayurmadnani
Reply   •   1 楼
mayurmadnani    5 年前

首先,使用指定的键进行排序,您可以获得索引顺序。你按顺序重新排列字典中剩下的列表。

unsorted_my_dict = {
'key_one': [1, 6, 2, 3],
'key_two': [4, 1, 9, 7],
'key_three': [1, 2, 4, 3],
}


def sort_parallel_by_key(my_dict, key):
    def sort_by_indices(idx_seq):
        return {k: [v[i] for i in idx_seq] for k, v in my_dict.items()}

    indexes = [idx for idx, _ in sorted(enumerate(my_dict[key]), key=lambda foo: foo[1])]
    return sort_by_indices(indexes)


print(sort_parallel_by_key(unsorted_my_dict, 'key_three'))
ShadowRanger
Reply   •   2 楼
ShadowRanger    5 年前

zip 将键放在一起,根据相关项对键函数进行排序,然后 拉链 再次恢复原始表单:

sorted_value_groups = sorted(zip(*unsorted_my_dict.values()), key=lambda _, it=iter(unsorted_my_dict['key_three']): next(it))
sorted_values = zip(*sorted_value_groups)
sorted_my_dict = {k: list(newvals) for k, newvals in zip(unsorted_my_dict, sorted_values)}

一点也不干净,我主要是为了好玩才贴的。一个班轮是:

sorted_my_dict = {k: list(newvals) for k, newvals in zip(unsorted_my_dict, zip(*sorted(zip(*unsorted_my_dict.values()), key=lambda _, it=iter(unsorted_my_dict['key_three']): next(it))))}

这是因为,当 dict 迭代顺序不保证在3.7之前,对于未修改的订单,该顺序保证可重复。 双关语 . 同样, key 函数从开始到结束都是按顺序执行的,所以通过重复迭代来提取键是安全的。我们只需分离所有值,按索引对它们进行分组,按索引键对组进行排序,按键对它们进行重新分组,然后将它们重新附加到原始键上。

输出完全按照要求进行(原始键的顺序保留在cpython 3.6或任何python 3.7或更高版本上):

sorted_my_dict = {
   'key_one': [1,6,3,2],
   'key_two': [4,1,7,9],
   'key_three': [1,2,3,4]
}
Olivier Melançon
Reply   •   3 楼
Olivier Melançon    5 年前

你可以先分类 enumerate 以恢复所需的索引顺序,然后按该顺序重新排列每个列表。

my_dict = {
   'key_one': [1,6,2,3],
   'key_two': [4,1,9,7],
   'key_three': [1,2,4,3],
}


def parallel_sort(d, key):
    index_order = [i for i, _ in sorted(enumerate(d[key]), key=lambda x: x[1])]
    return {k: [v[i] for i in index_order] for k, v in d.items()}

print(parallel_sort(my_dict, 'key_three'))

产量

{'key_one': [1, 6, 3, 2],
 'key_two': [4, 1, 7, 9],
 'key_three': [1, 2, 3, 4]}