通过公共密钥对字典列表进行排序,并将未知值移动到结尾

时间:2016-04-28 10:23:03

标签: sorting python-3.x

我有一个函数返回sorted()的一个键函数,目标是一个dicts列表。一个工作的例子是:

this = '4here'

但是我希望该函数能够处理缺失值:

def sort2key(sortKey, **kwargs):

    def attrgetter(obj):
        try:
            theItem = obj[sortKey]
        except:
            theItem = None
        finally:
            return theItem

    return attrgetter

input = [
    {'id':0, 'x': 2, 'y': 2},
    {'id':1, 'x': 1, 'y': 0},
    {'id':2, 'x': 0, 'y': 1}
]

theSort = {'sortKey': 'x'}

output = sorted(input, key=sort2key(**theSort))

print(input)
print(output)

>>> [{'x': 2, 'id': 0, 'y': 2}, {'x': 1, 'id': 1, 'y': 0}, {'x': 0, 'id': 2, 'y': 1}]
>>> [{'x': 0, 'id': 2, 'y': 1}, {'x': 1, 'id': 1, 'y': 0}, {'x': 2, 'id': 0, 'y': 2}]

但是之前的代码会强制启动缺少x的dict - 它需要是开始或结束,具体取决于排序设置:

[
    {'id':0, 'x': 2, 'y': 2},
    {'id':1, 'x': 1, 'y': 0},
    {'id':2,         'y': 1}
]

此外,在这种情况下,x的值是数字,但它们可以是字符串或其他类型。

有没有办法强制将未知值强加到最后?

2 个答案:

答案 0 :(得分:0)

您可以使用lambda函数和get类型的dict方法。这是你的代码:

  Input = [
      {'id':0, 'x': 2, 'y': 2},
      {'id':1, 'x': 1, 'y': 0},
      {'id':2, 'x': 0, 'y': 1}  ]

  sortKey = 'id' # Use max for ToEnd setting
  unknown = max( [ elt[sortKey] for elt in Input if sortKey in elt ] )  

  Output  = sorted(Input, key=lambda X: X.get(sortKey, unknown))

  for elt in Output:
     print(elt)

dict.get(a,b)返回与键a相关的值(如果存在)或默认值b。

对于混合数据,您可以使用:max( [ str(elt[sortKey]) for elt in Input if sortKey in elt ] ),因此可以比较不同类型的值。

您只需使用min / max功能即可在ToEnd和ToStart设置之间切换。

答案 1 :(得分:0)

以下是使用@ nino_701的comment

的工作示例
def sort2key(sortKey, minVal, maxVal, unknowns='toEnd', **kwargs):

    def attrgetter(obj):
        try:
            theItem = obj[sortKey]
        except:
            theItem = minVal if unknowns == 'toStart' else maxVal
        finally:
            return theItem

    return attrgetter

input = [
    {'id':0, 'x': 2, 'y': 2},
    {'id':1,         'y': 0},
    {'id':2, 'x': 0, 'y': 1}
]

theSort = {'sortKey': 'x'}

minVal = min((x[theSort['sortKey']] for x in input if theSort['sortKey'] in x))
maxVal = max((x[theSort['sortKey']] for x in input if theSort['sortKey'] in x))

output = sorted(input, key=sort2key(minVal = minVal, maxVal = maxVal, unknowns='toStart', **theSort))
output2 = sorted(input, key=sort2key(minVal = minVal, maxVal = maxVal, unknowns='toEnd', **theSort))

print(input)
print(output)
print(output2)

>>> [{'id': 0, 'y': 2, 'x': 2}, {'id': 1, 'y': 0}, {'id': 2, 'y': 1, 'x': 0}]
>>> [{'id': 1, 'y': 0}, {'id': 2, 'y': 1, 'x': 0}, {'id': 0, 'y': 2, 'x': 2}]
>>> [{'id': 2, 'y': 1, 'x': 0}, {'id': 0, 'y': 2, 'x': 2}, {'id': 1, 'y': 0}]