我想按字典键对字典列表进行排序,我不想区分大写和小写字符。
dict1 = {'name':'peter','phone':'12355'}
dict2 = {'name':'Paul','phone':'545435'}
dict3 = {'name':'klaus','phone':'55345'}
dict4 = {'name':'Krishna','phone':'12345'}
dict5 = {'name':'Ali','phone':'53453'}
dict6 = {'name':'Hans','phone':'765756'}
list_of_dicts = [dict1,dict2,dict3,dict4,dict5,dict6]
key_field = 'name'
list_of_dicts.sort(key=itemgetter(key_field))
# how to combine key=itemgetter(key_field) and key=str.lower?
for list_field in list_of_dicts:
print list_field[key_field]
应提供
Ali, Hans, klaus, Krishna, Paul, peter
而不是
klaus, peter, Ali, Hans, Krishna, Paul
答案 0 :(得分:14)
这个怎么样:
list_of_dicts.sort(key=lambda a: a['name'].lower())
答案 1 :(得分:10)
在一般情况下,您需要编写密钥提取功能以进行排序;只有在特殊的(虽然很重要的)情况下,您可以重复使用现有的可调用来为您提取密钥,或者只是将几个现有的密码连接起来(使用lambda
以“快速和脏”的方式)没有内置的方法来进行功能组合。)
如果您经常需要执行这两种操作来进行密钥提取(获取项目并在该项目上调用方法),我建议:
def combiner(itemkey, methodname, *a, **k):
def keyextractor(container):
item = container[itemkey]
method = getattr(item, methodname)
return method(*a, **k)
return keyextractor
所以listofdicts.sort(key=combiner('name', 'lower'))
适用于您的情况。
请注意,虽然过度泛化具有成本,有品味和适度的泛化(留下项密钥,方法名称和方法参数,如果有的话,在这种情况下由运行时确定)通常会带来好处 - 一个通用功能,而不是更多复杂的十几个特定的和专门的(使用提取器,调用方法或两者,在他们的代码中硬连线),将更容易维护(当然,更容易重用! - )。
答案 2 :(得分:4)
为了便于阅读,你可能应该使用lambda。但是作为对高阶函数的有趣研究,这里是Python中q-combinator的扩展版本(也称为奇怪的鸟类组合子)。这允许您通过组合两个函数来创建新函数
def compose(inner_func, *outer_funcs):
if not outer_funcs:
return inner_func
outer_func = compose(*outer_funcs)
return lambda *args, **kwargs: outer_func(inner_func(*args, **kwargs))
from operator import itemgetter, methodcaller
name_lowered = compose(itemgetter('name'), methodcaller('lower'))
print(name_lowered( {'name': 'Foo'} ))
如果在compose
函数中反转内部和外部的定义,则会获得更传统的b-combinator(bluebird)。我更喜欢q-combinator,因为它与unix管道相似。
答案 3 :(得分:4)
此解决方案将使用您的系统区域设置,作为奖励,它将根据当前区域设置对最终的其他字符进行排序(将“u”放在德语区域设置之后等等。)
from locale import setlocale, strxfrm, LC_ALL
import operator
# call setlocale to init current locale
setlocale(LC_ALL, "")
def locale_keyfunc(keyfunc):
def locale_wrapper(obj):
return strxfrm(keyfunc(obj))
return locale_wrapper
list_of_dicts.sort(key=locale_keyfunc(operator.itemgetter("name")))
这当然使用了区域设置排序是您希望使用.lower()模拟的用户界面“自然”排序。
我很惊讶python的locale
模块是未知且未使用的,它肯定是我编写的应用程序中的一个重要组件(翻译成多种语言,但语言环境模块对于获取非常重要一个模块正确。例如:瑞典语'V'和'W'类似,所以你必须整理它们。locale
为你完成所有这些。)。
在POSIX
区域设置(非默认)中,这将在“Z”之后恢复为“a”排序。
答案 4 :(得分:4)
就个人而言,我希望Python标准库中有两个函数(可能在functools中):
def compose(*funcs):
"""
Compose any number of unary functions into a single unary
function.
>>> import textwrap
>>> str.strip(textwrap.dedent(compose.__doc__)) == compose(str.strip, textwrap.dedent)(compose.__doc__)
True
"""
compose_two = lambda f1, f2: lambda v: f1(f2(v))
return reduce(compose_two, funcs)
def method_caller(method_name, *args, **kwargs):
"""
Return a function that will call a named method on the
target object with optional positional and keyword
arguments.
>>> lower = method_caller('lower')
>>> lower('MyString')
'mystring'
"""
def call_method(target):
func = getattr(target, method_name)
return func(*args, **kwargs)
return call_method
我已经在jaraco.util.functools中实现了这些功能。
无论哪种方式,现在您的代码都非常清晰,自我记录且功能强大(IMO)。
lower = method_caller('lower')
get_name = itemgetter('name')
lowered_name = compose(lower, get_name)
list_of_dicts.sort(key=lowered_name)
答案 5 :(得分:4)
from functools import partial
def nested_funcs(*funcs):
return partial(reduce, lambda arg, func: func(arg), funcs)
sorted(list_of_dicts, key=nested_funcs(itemgetter('name'), str.strip, str.lower))
答案 6 :(得分:2)
def lower_getter(field):
def _getter(obj):
return obj[field].lower()
return _getter
list_of_dicts.sort(key=lower_getter(key_field))