python - كيف يمكنني فرز القاموس عن طريق المفتاح؟




sorting dictionary (19)

كان قاموس بايثون غير مجهول قبل Python 3.6. في تطبيق CPython من Python 3.6 ، يحتفظ القاموس ترتيب الإدراج. من Python 3.7 ، سيصبح هذا ميزة لغوية.

إذا كنت ترغب في فرز dict المتداخلة بما في ذلك sub-dict داخل ، فيمكنك القيام بما يلي:

test_dict = {'a': 1, 'c': 3, 'b': {'b2': 2, 'b1': 1}}

def dict_reorder(item):
    if isinstance(item, dict):
        item = {k: v for k, v in sorted(item.items())}
        for k, v in item.items():
            if isinstance(v, dict):
                item[k] = dict_reorder(v)
    return item

reordered_dict = dict_reorder(test_dict)

https://gist.github.com/ligyxy/f60f0374defc383aa098d44cfbd318eb

ما الذي سيكون طريقة لطيفة للانتقال من {2:3, 1:89, 4:5, 3:0} إلى {1:89, 2:3, 3:0, 4:5} ؟
راجعت بعض المشاركات ولكنهم جميعًا استخدموا عامل التشغيل "الذي تم فرزه" الذي يقوم بإرجاع tuples.


الرجال يعقدون الأمور معقدة ... إنها حقا بسيطة

from pprint import pprint
Dict={'B':1,'A':2,'C':3}
pprint(Dict)

الناتج هو:

{'A':2,'B':1,'C':3}

الطريقة الأكثر إيجازًا التي لم يرد ذكرها في أي من الإجابات الأخرى هي على الأرجح هذه الطريقة:

>>> d = {2:3, 1:89, 4:5, 3:0}
>>> dict(sorted(d.items()))
{1: 89, 2: 3, 3: 0, 4: 5}

كما ذكر آخرون ، قواميس غير مرتبة بطبيعتها. ومع ذلك ، إذا كانت المشكلة هي فقط عرض القواميس بطريقة مرتبة ، يمكنك تجاوز طريقة __str__ في فئة فرعية من القاموس ، واستخدام فئة هذا القاموس بدلاً من dict . على سبيل المثال.

class SortedDisplayDict(dict):
   def __str__(self):
       return "{" + ", ".join("%r: %r" % (key, self[key]) for key in sorted(self)) + "}"


>>> d = SortedDisplayDict({2:3, 1:89, 4:5, 3:0})
>>> d
{1: 89, 2: 3, 3: 0, 4: 5}

لاحظ أن هذا لا يغير شيئًا عن كيفية تخزين المفاتيح ، أو الترتيب الذي ستعود إليه عند التكرار فوقها ، إلخ ، فقط كيف يتم عرضها print أو في وحدة تحكم python.


سوف تولد بالضبط ما تريد:

 D1 = {2:3, 1:89, 4:5, 3:0}

 sort_dic = {}

 for i in sorted(D1):
     sort_dic.update({i:D1[i]})
 print sort_dic


{1: 89, 2: 3, 3: 0, 4: 5}

ولكن هذه ليست طريقة الكتابة للقيام بذلك ، لأنه ، يمكن أن تظهر سلوكًا متميزًا مع قواميس مختلفة ، والتي تعلمتها حديثًا. ومن ثم تم اقتراح طريقة مثالية من قبل تيم في استجابة بلدي الاستعلام الذي أتشارك هنا.

from collections import OrderedDict
sorted_dict = OrderedDict(sorted(D1.items(), key=lambda t: t[0]))

ببساطة:

d = {2:3, 1:89, 4:5, 3:0}
sd = sorted(d.items())

for k,v in sd:
    print k, v

انتاج:

1 89
2 3
3 0
4 5

هنا وجدت بعض الحلول الأبسط لفرز pprint dict باستخدام المفتاح pprint . على سبيل المثال.

>>> x = {'a': 10, 'cd': 20, 'b': 30, 'az': 99} 
>>> print x
{'a': 10, 'b': 30, 'az': 99, 'cd': 20}

ولكن أثناء استخدام pprint ، فسوف تعرض الإملاء المصنّف

>>> import pprint 
>>> pprint.pprint(x)
{'a': 10, 'az': 99, 'b': 30, 'cd': 20}

من وثائق مكتبة collections Python :

>>> from collections import OrderedDict

>>> # regular unsorted dictionary
>>> d = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}

>>> # dictionary sorted by key -- OrderedDict(sorted(d.items()) also works
>>> OrderedDict(sorted(d.items(), key=lambda t: t[0]))
OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])

>>> # dictionary sorted by value
>>> OrderedDict(sorted(d.items(), key=lambda t: t[1]))
OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])

>>> # dictionary sorted by length of the key string
>>> OrderedDict(sorted(d.items(), key=lambda t: len(t[0])))
OrderedDict([('pear', 1), ('apple', 4), ('orange', 2), ('banana', 3)])

l = dict.keys()
l2 = l
l2.append(0)
l3 = []
for repeater in range(0, len(l)):
    smallnum = float("inf")
    for listitem in l2:
        if listitem < smallnum:
            smallnum = listitem
    l2.remove(smallnum)
    l3.append(smallnum)
l3.remove(0)
l = l3

for listitem in l:
    print(listitem)

وجدت طريقة أخرى:

import json
print json.dumps(d, sort_keys = True)

محدث:
1. هذا أيضا فرز الأشياء المتداخلة (شكراDanielF).
2. القواميس python غير مرتبة لذلك هذا هو sutable للطباعة أو تعيين إلى str فقط.


from operator import itemgetter
# if you would like to play with multiple dictionaries then here you go:
# Three dictionaries that are composed of first name and last name.
user = [
    {'fname': 'Mo', 'lname': 'Mahjoub'},
    {'fname': 'Abdo', 'lname': 'Al-hebashi'},
    {'fname': 'Ali', 'lname': 'Muhammad'}
]
#  This loop will sort by the first and the last names.
# notice that in a dictionary order doesn't matter. So it could put the first name first or the last name first. 
for k in sorted (user, key=itemgetter ('fname', 'lname')):
    print (k)

# This one will sort by the first name only.
for x in sorted (user, key=itemgetter ('fname')):
    print (x)

بيثون ديكتس غير مرتب. عادة ، هذه ليست مشكلة حيث أن حالة الاستخدام الأكثر شيوعًا هي إجراء بحث.

إن أبسط طريقة لفعل ما تريد هو إنشاء collections.OrderedDict إدخال أمر إدخال العناصر بترتيب مفروض.

ordered_dict = collections.OrderedDict([(k, d[k]) for k in sorted(d.keys())])

إذا كنت بحاجة إلى التكرار ، كما اقترح الآخرون أعلاه ، فإن أبسط طريقة هي التكرار عبر مفاتيح تم فرزها. أمثلة-

قيم الطباعة مرتبة حسب المفاتيح:

# create the dict
d = {k1:v1, k2:v2,...}
# iterate by keys in sorted order
for k in sorted(d.keys()):
    value = d[k]
    # do something with k, value like print
    print k, value

الحصول على قائمة القيم مرتبة حسب المفاتيح:

values = [d[k] for k in sorted(d.keys())]

إذا كان لديك أمر ، على سبيل المثال:

not_ordered_dict = {5 : "5555", 9 : "9999", 1 : "1111"}

ordered_dict = {}

for key in sorted(not_ordered_dict):
    ordered_dict[key] = not_ordered_dict[key]   

هناك عدد من وحدات Python التي توفر تطبيقات القاموس التي تحافظ تلقائيًا على المفاتيح في الترتيب الذي تم فرزه. ضع في sortedcontainers وحدة sortedcontainers التي هي نقي Python والتطبيقات Fast-C. هناك أيضًا مقارنة أداء مع الخيارات الشائعة الأخرى التي تم قياسها مقابل بعضها البعض.

إن استخدام أمر مرتبة هو حل غير ملائم إذا كنت بحاجة إلى إضافة أزواج المفاتيح / القيم وإزالتها باستمرار أثناء تكرارها أيضًا.

>>> from sortedcontainers import SortedDict
>>> d = {2:3, 1:89, 4:5, 3:0}
>>> s = SortedDict(d)
>>> s.items()
[(1, 89), (2, 3), (3, 0), (4, 5)]

يدعم النوع SortedDict أيضًا عمليات البحث عن المواقع المفهرسة والحذف ، وهو أمر غير ممكن مع نوع الإملاء المدمج.

>>> s.iloc[-1]
4
>>> del s.iloc[2]
>>> s.keys()
SortedSet([1, 2, 4])

قواميس بايثون القياسية غير مرتبة. حتى لو قمت بفرز أزواج (المفتاح والقيمة) ، لن تتمكن من تخزينها في أمر بطريقة تحفظ الأمر.

أسهل طريقة هي استخدام OrderedDict ، الذي يتذكر الترتيب الذي تم فيه إدراج العناصر:

In [1]: import collections

In [2]: d = {2:3, 1:89, 4:5, 3:0}

In [3]: od = collections.OrderedDict(sorted(d.items()))

In [4]: od
Out[4]: OrderedDict([(1, 89), (2, 3), (3, 0), (4, 5)])

ناهيك عن الطريقة التي تطبع بها od ؛ ستعمل كما هو متوقع:

In [11]: od[1]
Out[11]: 89

In [12]: od[3]
Out[12]: 0

In [13]: for k, v in od.iteritems(): print k, v
   ....: 
1 89
2 3
3 0
4 5

بايثون 3

بالنسبة لمستخدمي Python 3 ، يحتاج المرء إلى استخدام .items() بدلاً من .iteritems() :

In [13]: for k, v in od.items(): print(k, v)
   ....: 
1 89
2 3
3 0
4 5

في بايثون 3.

>>> D1 = {2:3, 1:89, 4:5, 3:0}
>>> for key in sorted(D1):
    print (key, D1[key])

يعطي

1 89
2 3
3 0
4 5

dictionary = {1:[2],2:[],5:[4,5],4:[5],3:[1]}

temp=sorted(dictionary)
sorted_dict = dict([(k,dictionary[k]) for i,k in enumerate(temp)])

sorted_dict:
         {1: [2], 2: [], 3: [1], 4: [5], 5: [4, 5]}

توضح مقارنة التوقيت للطريقتين في 2.7 أنها متطابقة تقريبًا:

>>> setup_string = "a = sorted(dict({2:3, 1:89, 4:5, 3:0}).items())"
>>> timeit.timeit(stmt="[(k, val) for k, val in a]", setup=setup_string, number=10000)
0.003599141953657181

>>> setup_string = "from collections import OrderedDict\n"
>>> setup_string += "a = OrderedDict({1:89, 2:3, 3:0, 4:5})\n"
>>> setup_string += "b = a.items()"
>>> timeit.timeit(stmt="[(k, val) for k, val in b]", setup=setup_string, number=10000)
0.003581275490432745 

هذا يسأل السؤال الخطأ. السؤال الصحيح هو: لماذا أقضي الوقت في فرز الجوارب؟ كم يكلف على أساس سنوي ، عندما كنت أقدر وقت فراغك للوحدات النقدية X من اختيارك؟

وفي أكثر الأحيان ، ليس هذا مجرد وقت حر ، إنه وقت حر في الصباح ، يمكنك إنفاقه في السرير ، أو احتساء قهوتك ، أو ترك وقت مبكر قليلاً وعدم الوقوع في حركة المرور.

من الجيد في كثير من الأحيان العودة إلى الوراء ، والتفكير في طريقة لحل المشكلة.

وهناك طريقة!

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

من الأفضل عدم وجود أي اختلاف بين الجوارب اليمنى واليسرى ، ولكنها ليست حرجة. إذا كانت الجورب متماثلة من اليسار إلى اليمين ، فإن العثور على زوج هو عملية O (1) ، وفرز الجوارب هو عملية O (M) تقريبية ، حيث M هي عدد الأماكن في منزلك ، والتي قمت بتناثرها مع الجوارب ، ومن الناحية المثالية بعض رقم ثابت صغير.

إذا اخترت زوجًا فاخرًا مع جورب مختلف يمين ويسار ، فقم بعمل نوع دلو كامل إلى دلاء القدم اليمنى واليسرى يأخذ O (N + M) ، حيث N هو عدد الجوارب و M هو نفسه كما هو مذكور أعلاه. يمكن لشخص آخر إعطاء صيغة متوسط ​​تكرار العثور على الزوج الأول ، ولكن أسوأ حالة للعثور على زوج مع بحث أعمى هو N / 2 + 1 ، والذي يصبح حالة غير متوقعة بشكل كبير بالنسبة إلى N معقولة. يمكن تسريع ذلك باستخدام الصورة المتقدمة خوارزميات الاعتراف والاستدلال ، عند مسح كومة من الجوارب غير المفردة مع Mk1 مقلة العين .

لذا ، فإن الخوارزمية لتحقيق كفاءة الاقتران (1) على شكل جورب (بافتراض جورب متناظر) هي:

  1. تحتاج إلى تقدير عدد أزواج الجوارب التي ستحتاجها لبقية حياتك ، أو ربما حتى تتقاعد وتتحرك إلى المناخ الأكثر دفئًا دون الحاجة إلى ارتداء الجوارب مرة أخرى. إذا كنت شابًا ، يمكنك أيضًا تقدير الوقت المستغرق قبل أن يكون لدينا جميعًا روبوتات الفرز في منازلنا ، وتصبح المشكلة بأكملها غير ذات صلة.

  2. يجب أن تعرف كيف يمكنك طلب جوربك المختار بالجملة ، ومقدار تكلفته ، وما تقدمه.

  3. اطلب الجوارب!

  4. تخلص من الجوارب القديمة الخاصة بك.

خطوة بديلة 3 تنطوي على مقارنة تكاليف شراء نفس الكمية من الجوارب أرخص ربما بضعة أزواج في وقت واحد على مر السنين وإضافة تكلفة فرز الجوارب ، ولكن تأخذ كلمتي لذلك: شراء بالجملة بالجملة أرخص! أيضا ، زيادة الجوارب في التخزين في القيمة بمعدل تضخم أسعار الأسهم ، وهو أكثر مما كنت تحصل على العديد من الاستثمارات. ثم مرة أخرى هناك أيضا تكلفة التخزين ، ولكن الجوارب حقا لا تأخذ مساحة كبيرة على الرف العلوي للخزانة.

تم حل المشكلة. لذا ، فقط احصل على جوارب جديدة ، ارمي / تبرع بأولائك القدامى ، واعيش بسعادة بعد أن عرفت أنك توفر المال والوقت كل يوم لبقية حياتك.





python sorting dictionary