Python 3:词典列表的单一自定义排序功能?

时间:2016-12-16 06:20:47

标签: python list sorting dictionary

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

下面是一个简化的工作示例。我已经解决了这些问题(感谢SO的一些帮助)。示例输入在"桶和#34;中示出。字典。

我试图找到一种方法来解决问题"底部的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用于在数据集中返回异常值时,这将发生并且完全正常。 "传递"是因为他们不需要处理

2 个答案:

答案 0 :(得分: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))

答案 1 :(得分:0)

这是另一种方法,更模块化,可能更容易阅读 - 仍然没有考虑到尝试/排除但它开始看起来有点难看

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)