سؤال

لدي قائمة من القواميس و تريد كل بند من أن تكون مرتبة حسب خاصية معينة القيم.

تأخذ في الاعتبار مجموعة أدناه ،

[{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}]

عندما يتم فرزها من قبل name, أن تصبح

[{'name':'Bart', 'age':10}, {'name':'Homer', 'age':39}]
هل كانت مفيدة؟

المحلول

قد تبدو أنظف باستخدام مفتاح بدلا cmp:

newlist = sorted(list_to_be_sorted, key=lambda k: k['name']) 

أو كما J. F. سيباستيان وغيرها اقترح ،

from operator import itemgetter
newlist = sorted(list_to_be_sorted, key=itemgetter('name')) 

للتأكد من اكتمالها (كما أشار في تصريحات fitzgeraldsteele) ، إضافة reverse=True فرز تنازلي

newlist = sorted(l, key=itemgetter('name'), reverse=True)

نصائح أخرى

import operator

لفرز قائمة القواميس قبل key='اسم':

list_of_dicts.sort(key=operator.itemgetter('name'))

لفرز قائمة القواميس قبل key='عمر':

list_of_dicts.sort(key=operator.itemgetter('age'))

إذا كنت ترغب في فرز قائمة من مفاتيح متعددة يمكنك القيام بما يلي:

my_list = [{'name':'Homer', 'age':39}, {'name':'Milhouse', 'age':10}, {'name':'Bart', 'age':10} ]
sortedlist = sorted(my_list , key=lambda elem: "%02d %s" % (elem['age'], elem['name']))

بل هي hackish ، لأنه يعتمد على تحويل القيم إلى سلسلة واحدة التمثيل وعلى سبيل المقارنة ، ولكنه يعمل كما هو متوقع على الأرقام بما في ذلك تلك السلبية (على الرغم من أنك سوف تحتاج إلى تنسيق سلسلة الخاص بك بشكل مناسب مع صفر سائد إذا كنت تستخدم أرقام)

my_list = [{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}]

my_list.sort(lambda x,y : cmp(x['name'], y['name']))

my_list الآن سوف تكون ما تريد.

(3 سنوات) تحرير لإضافة:

الجديد key الحجة هي أكثر كفاءة و أكثر إتقانا.أفضل إجابة تبدو الآن مثل:

my_list = sorted(my_list, key=lambda k: k['name'])

...لامدا ، المنظمة البحرية الدولية ، أسهل للفهم من operator.itemgetter, لكن YMMV.

import operator
a_list_of_dicts.sort(key=operator.itemgetter('name'))

'مفتاح' يستخدم نوعا من قيمة التعسفي و 'itemgetter' مجموعات قيمة كل بند 'اسم' السمة.

a = [{'name':'Homer', 'age':39}, ...]

# This changes the list a
a.sort(key=lambda k : k['name'])

# This returns a new list (a is not modified)
sorted(a, key=lambda k : k['name']) 

أعتقد أنك تعني:

[{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}]

هذا من شأنه أن يكون فرز مثل هذا:

sorted(l,cmp=lambda x,y: cmp(x['name'],y['name']))

باستخدام Schwartzian تحويل من بيرل ،

py = [{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}]

هل

sort_on = "name"
decorated = [(dict_[sort_on], dict_) for dict_ in py]
decorated.sort()
result = [dict_ for (key, dict_) in decorated]

يعطي

>>> result
[{'age': 10, 'name': 'Bart'}, {'age': 39, 'name': 'Homer'}]

أكثر على بيرل Schwartzian تحويل

في علوم الكمبيوتر ، Schwartzian تحويل هو البرمجة Perl لغة تستخدم لتحسين كفاءة الفرز قائمة من العناصر.هذا المصطلح المناسب المقارنة على أساس الفرز عندما يأمر في الواقع بناء على طلب من خاصية معينة (المفتاح) من العناصر ، حيث الحوسبة تلك الممتلكات مكثفة العملية التي يجب أن يتم تنفيذ الحد الأدنى من عدد من المرات.على Schwartzian تحول ملحوظ في أنه لا يستخدم اسمه المؤقتة المصفوفات.

هل يمكن استخدام مخصص وظيفة مقارنة ، أو يمكن أن تمر في وظيفة يحسب فرز مخصص الرئيسية.التي عادة ما تكون أكثر كفاءة كما المفتاح هو فقط يحسب مرة واحدة لكل بند ، في حين أن وظيفة مقارنة سيكون اتصلت عدة مرات أكثر.

يمكنك أن تفعل ذلك بهذه الطريقة:

def mykey(adict): return adict['name']
x = [{'name': 'Homer', 'age': 39}, {'name': 'Bart', 'age':10}]
sorted(x, key=mykey)

ولكن المكتبة القياسية يحتوي على روتين عام من أجل الحصول على عناصر من كائنات التعسفي: itemgetter.لذا جرب هذا بدلا من ذلك:

from operator import itemgetter
x = [{'name': 'Homer', 'age': 39}, {'name': 'Bart', 'age':10}]
sorted(x, key=itemgetter('name'))

لديك لتنفيذ الخاصة بك وظيفة مقارنة يقارن بين القواميس من القيم من اسم مفاتيح.انظر الفرز مصغرة كيفية من PythonInfo ويكي

هنا هو البديل الحل العام - ومن أنواع عناصر ديكت من المفاتيح و القيم.والاستفادة من ذلك - لا تحتاج إلى تحديد مفاتيح سيكون العمل إذا كان بعض مفاتيح مفقودة في بعض القواميس.

def sort_key_func(item):
    """ helper function used to sort list of dicts

    :param item: dict
    :return: sorted list of tuples (k, v)
    """
    pairs = []
    for k, v in item.items():
        pairs.append((k, v))
    return sorted(pairs)
sorted(A, key=sort_key_func)

في وقت نحن بحاجة إلى استخدام lower() على سبيل المثال

lists = [{'name':'Homer', 'age':39},
  {'name':'Bart', 'age':10},
  {'name':'abby', 'age':9}]

lists = sorted(lists, key=lambda k: k['name'])
print(lists)
# [{'name':'Bart', 'age':10}, {'name':'Homer', 'age':39}, {'name':'abby', 'age':9}]

lists = sorted(lists, key=lambda k: k['name'].lower())
print(lists)
# [ {'name':'abby', 'age':9}, {'name':'Bart', 'age':10}, {'name':'Homer', 'age':39}]

حاولت شيئا من هذا القبيل:

my_list.sort(key=lambda x: x['name'])

عملت على الاعداد الصحيحه كذلك.

استخدام الباندا حزمة هو أسلوب آخر ، على الرغم من أنه من وقت التشغيل على نطاق واسع هو أبطأ بكثير من أكثر الأساليب التقليدية المقترحة من قبل الآخرين:

import pandas as pd

listOfDicts = [{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}]
df = pd.DataFrame(listOfDicts)
df = df.sort_values('name')
sorted_listOfDicts = df.T.to_dict().values()

وفيما يلي بعض معايير القيم قائمة صغيرة و كبيرة (100k) قائمة dicts:

setup_large = "listOfDicts = [];\
[listOfDicts.extend(({'name':'Homer', 'age':39}, {'name':'Bart', 'age':10})) for _ in range(50000)];\
from operator import itemgetter;import pandas as pd;\
df = pd.DataFrame(listOfDicts);"

setup_small = "listOfDicts = [];\
listOfDicts.extend(({'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}));\
from operator import itemgetter;import pandas as pd;\
df = pd.DataFrame(listOfDicts);"

method1 = "newlist = sorted(listOfDicts, key=lambda k: k['name'])"
method2 = "newlist = sorted(listOfDicts, key=itemgetter('name')) "
method3 = "df = df.sort_values('name');\
sorted_listOfDicts = df.T.to_dict().values()"

import timeit
t = timeit.Timer(method1, setup_small)
print('Small Method LC: ' + str(t.timeit(100)))
t = timeit.Timer(method2, setup_small)
print('Small Method LC2: ' + str(t.timeit(100)))
t = timeit.Timer(method3, setup_small)
print('Small Method Pandas: ' + str(t.timeit(100)))

t = timeit.Timer(method1, setup_large)
print('Large Method LC: ' + str(t.timeit(100)))
t = timeit.Timer(method2, setup_large)
print('Large Method LC2: ' + str(t.timeit(100)))
t = timeit.Timer(method3, setup_large)
print('Large Method Pandas: ' + str(t.timeit(1)))

#Small Method LC: 0.000163078308105
#Small Method LC2: 0.000134944915771
#Small Method Pandas: 0.0712950229645
#Large Method LC: 0.0321750640869
#Large Method LC2: 0.0206089019775
#Large Method Pandas: 5.81405615807

دعونا نقول أنا ح ذاقت القاموس D مع العناصر أدناه.لفرز فقط استخدام مفتاح حجة في فرز لتمرير وظيفة مخصصة على النحو التالي

D = {'eggs': 3, 'ham': 1, 'spam': 2}

def get_count(tuple):
    return tuple[1]

sorted(D.items(), key = get_count, reverse=True)
or
sorted(D.items(), key = lambda x: x[1], reverse=True)  avoiding get_count function call

https://wiki.python.org/moin/HowTo/Sorting/#Key_Functions

هنا جوابي على ذات السؤال على الفرز من خلال أعمدة متعددة.كما أنها تعمل على تتدهور الحالة التي يكون فيها عدد الأعمدة هو واحد فقط.

إذا كنت لا تحتاج الأصلي list من dictionaries, هل يمكن تعديله في نفس المكان مع sort() طريقة استخدام مفتاح مخصص وظيفة.

الوظيفة الرئيسية:

def get_name(d):
    """ Return the value of a key in a dictionary. """

    return d["name"]

على list فرز:

data_one = [{'name': 'Homer', 'age': 39}, {'name': 'Bart', 'age': 10}]

الفرز في نفس المكان:

data_one.sort(key=get_name)

إذا كنت في حاجة إلى الأصلي list, اتصل sorted() وظيفة فمررها list و مفتاح الوظيفة ، ثم تعيين عاد فرز list إلى متغير جديد:

data_two = [{'name': 'Homer', 'age': 39}, {'name': 'Bart', 'age': 10}]
new_data = sorted(data_two, key=get_name)

الطباعة data_one و new_data.

>>> print(data_one)
[{'name': 'Bart', 'age': 10}, {'name': 'Homer', 'age': 39}]
>>> print(new_data)
[{'name': 'Bart', 'age': 10}, {'name': 'Homer', 'age': 39}]

يمكنك استخدام itemgetter إذا كنت ترغب في النظر في الأداء. itemgetter يعمل عادة أسرع قليلا من امدا.

from operator import itemgetter
result = sorted(data, key=itemgetter('age'))  # this will sort list by property order 'age'.

يمكنك استخدام التعليمات البرمجية التالية

sorted_dct = sorted(dct_name.items(), key = lambda x : x[1])
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top