【问题标题】:Python 3: single custom sorting function for list of dictionaries?Python 3:字典列表的单个自定义排序功能?
【发布时间】:2016-12-16 06:20:46
【问题描述】:

我正在处理作为字典列表返回的数据。每个 dicts 都需要按其值排序,其中一些 dicts 需要“特别注意”,就像自定义排序模式一样。

下面是一个简化的工作示例。我自己解决了这些问题(感谢 SO 的一些帮助)。示例输入在“buckets”字典中进行了说明。

我正在尝试想办法将底部的 3 个单独的排序方法“折叠”成一个排序函数,以避免重复类似的代码。很难弄清楚。我编写的测试代码基本上只是重新创建了我在这里所做的,但是在一个函数中:-|

# returned data to sort
buckets = {
    'size_apparel' : [
        { 'doc_count': 86, 'key': 'M' },
        { 'doc_count': 12, 'key': 'S' },
        { 'doc_count': 44, 'key': 'L' },
        { 'doc_count': 44, 'key': 'Bazillion' } # outlier
    ],
    'size_jewelry' : [
        { 'doc_count': 86, 'key': '7' },
        { 'doc_count': 12, 'key': '4.5' },
        { 'doc_count': 10, 'key': '6' },
        { 'doc_count': 2, 'key': '5' }
    ],
    'color' : [
        { 'doc_count': 86, 'key': 'Zebra' },
        { 'doc_count': 12, 'key': 'Azure' },
        { 'doc_count': 44, 'key': 'Red' }
    ]
}

# list of all possible buckets, not used here but *could* be used
bucket_list = ['size_apparel','size_jewelry','state','color','cloth','style']

# custom sorting for apparel
apparel_map = ['S','M','L','XL','XXL','XXXL']

for key, value in buckets.items():

    # apparel as a custom sort map defined in apparel_map
    if key == 'size_apparel':
        try:
            buckets['size_apparel'] = sorted(buckets['size_apparel'], 
                key=lambda x:apparel_map.index(x['key']))
        except ValueError: 
            pass

    # jewelry sizes are sorted numerically, but need to be converted to float first
    elif key == 'size_jewelry':
        try:
            buckets['size_jewelry'] = sorted(buckets['size_jewelry'], 
                key=lambda k: float(k['key']))
        except ValueError:
            pass    

    # everything else: sort by doc count descending
    else:
        try:
            buckets[key] = sorted(buckets[key], key=lambda k: k['doc_count'], reverse=True)
        except ValueError:
            pass   

try/except 用于在数据集中返回异常值时,这将发生并且完全没问题。 “通行证”是因为他们不需要处理

【问题讨论】:

  • 您想要避免的“类似代码的重复”到底是什么?为什么必须将整数转换为浮点数?
  • 只发布你想要的输出。
  • 另外,为什么都是try: ...; except ValueError: pass?您要避免哪些错误?
  • 是的,也许没有办法折叠它们。我是一个 python 新手,我仍在寻找最正确和最简洁的方法来处理事情。关于浮点转换:这些数据实际上是以字符串的形式出现的。抱歉,我不清楚。当我对它们进行排序而不转换为浮点数时,它看起来像:10、10.5、11、4、4.5、5 等(帖子中的示例是简化的数据集)
  • @Robᵩ 使用该自定义排序时,如果数据中的“离群值”注释所指出的键未出现在服装地图中,python 会抛出“ValueError:'Bazillion'不在列表”。它存在于其他街区只是为了安全。这可能是不必要的,但以珠宝尺寸数据结尾的词并非闻所未闻。

标签: python list sorting dictionary


【解决方案1】:

是的,您可以将所有键选择逻辑移到一个函数中,并使循环看起来更简单。

这是一种方法。

def key_function(name):
    # custom sorting for apparel
    apparel_map = ['S','M','L','XL','XXL','XXXL']
    def key(d):
        if name == 'size_apparel':
            try:
                return apparel_map.index(d['key'])
            except ValueError:
                return len(apparel_map)
        elif name == 'size_jewelry':
            try:
                return float(d['key'])
            except ValueError:
                return sys.float_info.max
        return -d['doc_count']
    return key

for key, value in buckets.items():
    value.sort(key=key_function(key))

【讨论】:

  • 不知道为什么我的帖子被否决了,但这是一个非常优雅的解决方案,正是我想要的。谢谢!
【解决方案2】:

这是另一种方法,更模块化,也许更易于阅读 - 仍然没有考虑到 try/excepts,但它开始看起来有点难看

import sys,  operator

apparel_map = {k:i for i,k in enumerate(apparel_map)}
# or
apparel_map = {'S':0, 'M':1, 'L':2,'XL':3, 'XXL':4, 'XXXL':5}

my_key = operator.itemgetter('key')
doc_count = operator.itemgetter('doc_count')

def f(item):
    '''size_apparel key function'''
    try:
        return apparel_map[my_key(item)]
    except KeyError:
        return sys.maxsize

def g(item):
    '''size_jewelry key function'''
    try:
        return float(my_key(item))
    except ValueError:
        return sys.maxsize

def h(item):
    '''generic key function'''
    try:
        return doc_count(item) * -1
    except ValueError:
        return sys.maxsize

sort_keys = {'size_apparel' : f,
             'size_jewelry' : g}

for key, value in buckets.items():
    try:
        sort_key = sort_keys[key]
    except KeyError:
        sort_key = h
    value.sort(key = sort_key)

【讨论】:

    猜你喜欢
    • 2018-08-26
    • 2015-11-01
    • 2012-08-15
    • 2018-10-22
    • 1970-01-01
    • 2021-08-09
    • 1970-01-01
    • 2018-03-17
    • 1970-01-01
    相关资源
    最近更新 更多