对具有多个大小值的字典进行排序

Posted

技术标签:

【中文标题】对具有多个大小值的字典进行排序【英文标题】:Sorting a dictionary with multiple sized values 【发布时间】:2018-12-01 11:27:37 【问题描述】:

我有一本需要排序的字典。我了解无法对字典进行排序,因此我正在构建一个列表以根据索引执行排序。我遇到的问题是多个键之间存在重复值;此外,值可以是多个列表。

字典:

my_dict = 
    '1' : ['Red', 'McDonald\'s'],
    '2' : [['Orange', 'Wendy\'s'], ['Purple', 'Cookout']],
    '3' : ['Yellow', 'Longhorn'],
    '4' : ['Green', 'Subway'],
    '5' : ['Blue', 'Chipotle'],
    '6' : ['Indigo', 'Taco Bell'],
    '7' : [['Violet', 'Steak n Shake'], ['Dark Red', 'Five Guys']],
    '8' : ['Dark Orange', 'Wendy\'s'],
    '9' : ['Aqua', 'Firehouse Subs'],
    '10' : ['Magenta', 'McDonald\'s'],

我需要能够按键(数字)、颜色和餐厅对其进行排序。我遇到的问题是,当有重复时必须对打印进行分组,我无法弄清楚如何对我生成的列表进行正确排序。

按数字打印的示例:

1:
    Red, McDonald's

2:
    Orange, Wendy's
    Purple, Cookout

3:
    Yellow, Longhorn

...

按颜色打印的示例:

Aqua:
    Firehouse Subs, 9

Blue:
    Chipotle, 5

Dark Orange:
    Wendy's, 8

...

我对此的解决方案是创建一个列表,其中包含列表中的每个键和值。我还是新手,我认为这不是迭代这本字典的正确方法,但它适用于给定的字典。

sorted_number = []
for key, value in my_dict.items():
    if len(value[0][0]) > 1:
        working_list = (key, value[0][0], value[0][1], value[1][0], value[1][1])
        sorted_number.append(working_list)
    else:
        working_list = (key, value[0], value[1])
        sorted_number.append(working_list)

sorted_years = sorted(sorted_years, key=lambda y: y[0][0])
for i in sorted_years:
    print(':'.format(i[0]))
    if len(i) > 3:
         print('\t, '.format(i[1], i[2])
         print('\t, '.format(i[3], i[4]))
    else:
         print('\t, '.format(i[1], i[2]))

由于某些值是多个列表,if/else 语句确定该值是一个还是两个列表。然后,这将正确生成(数字、颜色、餐厅)或(数字、颜色、餐厅、颜色、餐厅)的列表,然后可以按数字对列表进行排序。问题是当我尝试按颜色或餐厅排序时。我知道我可以让列表只有三个元素以使排序正常工作,但是当我去打印时,我最终会得到多个 2 和 7。餐厅的结果相同。此外,这并不能解决多个餐厅的问题。我已经搜索和测试了大约五天,尝试不同的方法来解压字典,但这是我最接近解决这个问题的方法。任何帮助表示赞赏。提前致谢。

为清楚起见,这里是数字的打印迭代:

for i in sorted_number:
    print(':'.format(i[0]))
    if len(i) > 3:
        print('\t, '.format(i[1], i[2]))
        print('\t, '.format(i[3], i[4]))
    else:
        print('\t, '.format(i[1], i[2]))

【问题讨论】:

你读过这个python.org/dev/peps/pep-0265 @NitishKumar 值可以是一个或两个列表。除非我忽略了某些东西,否则解决方案是将字典转换为包含三个元素的列表,然后执行排序。 也许你可以使用 JSON '7' : [['Violet', 'Steak n Shake'], ['Dark Red', 'Five Guys']] 按颜色排序时,您希望如何放置?它应该在'8' : ['Dark Orange', 'Wendy\'s'](使用'Dark Red')之后还是'1' : ['Red', 'McDonald\'s'](使用'Violet')之后? @SergeBallesta 确实不用担心放置问题,只要在迭代列表或元组时,就可以按照描述打印信息。我的想法是制作一个像(5,Blue,Chipotle)这样的列表,但问题是当你去打印时,你会在 sortby 上有重复(例如 2 McDonald's)。在排序的重复条目上,您应该像这样打印:McDonald's: Red, 1 Magenta, 10 我无法正确格式化评论以显示正确的缩进。 【参考方案1】:

第一步是将dict转为list,将dict值以tuple数组的形式进行同质化。然后使用 itertools 模块中的groupBy 函数,您可以按所选参数进行分组。

class RestourantSorter:
    def __init__(self, source):
        self._rList = []
        """ Dict to list [(key, color, restourant name), ....] """
        for key, value in source.items():
            for color, rest in value if isinstance(value[0], list) else [value]:
                self._rList.append((key,color,rest))

    def _byIndex(self, x):
        return int(x[0])
    def _byColor(self, x):
        return x[1]
    def _byName(self, x):
        return x[2]

    def sort(self, sortFn):
        """ Sorted data [(key, [... values ...]), ....] """
        groups = []
        data = sorted(self._rList, key=sortFn)
        for k, g in groupby(data, sortFn):
            groups.append((k, list(g)))
        return groups

    def sortByIndex(self):
        return self.sort(self._byIndex)
    def sortByColor(self):
        return self.sort(self._byColor)
    def sortByName(self):
        return self.sort(self._byName)

工作REPL

【讨论】:

你这个人真了不起!我仍然是一名学生,到目前为止,课堂上的任何内容都没有触及 init 和 self 来建立一个班级。我们轻轻地谈到了班级建设的话题,老实说,我可能总共定义了一两次。这是我的第一堂编程课,我肯定需要进一步研究课堂建设;如果这甚至是正确的术语。我了解这门课中大约 90% 的情况;但是,我需要研究 self 和 init 才能完全掌握一切。再次感谢您!【参考方案2】:

当您希望更改或应用不同的索引时,字典并不理想。它只能有一把钥匙。如果您使用数字作为键,则很难切换到按颜色索引。这不是字典的优化目标。

您可以使用自定义类,但我更喜欢使用为处理数据而设计的第 3 方库。这是 Pandas 的示例。

import pandas as pd
from itertools import chain

chainer = chain.from_iterable

# calculate numeric keys including repeats, flat list
keys = list(chainer([k]*(len(v) if isinstance(v[0], list) else 1) \
                    for k, v in my_dict.items()))

# calculate color-name combinations, list of lists, each sublist of length 2
vals = list(chainer((v if isinstance(v[0], list) else [v] \
                    for v in my_dict.values())))

# create dataframe
df = pd.DataFrame(vals, columns=['color', 'name'], index=keys)

然后,您可以按数字键、颜色等对所需的输出进行分组,SO 上有许多可用的解决方案。可以进行排序,输出到dict 或使用print 进行迭代。

print(df)

          color            name
1           Red      McDonald's
2        Orange         Wendy's
2        Purple         Cookout
3        Yellow        Longhorn
4         Green          Subway
5          Blue        Chipotle
6        Indigo       Taco Bell
7        Violet   Steak n Shake
7      Dark Red       Five Guys
8   Dark Orange         Wendy's
9          Aqua  Firehouse Subs
10      Magenta      McDonald's

【讨论】:

以上是关于对具有多个大小值的字典进行排序的主要内容,如果未能解决你的问题,请参考以下文章

python 小技巧, 如何根据字典中的值的大小,对字典中的项排序

存储和排序同时具有 DateTime 和 Int 值的人员列表

python按值的长度对字典进行排序

通过具有日期值的单个键对对象数组进行排序

根据列表中的元素对列表作为值的字典进行排序

如何按值的 DateTime 属性对字典进行排序