ශබ්දකෝෂයේ අගය අනුව ශබ්ද කෝෂ ලැයිස්තුවක් වර්ග කරන්නේ කෙසේද?


1921

මා සතුව ශබ්ද කෝෂ ලැයිස්තුවක් ඇති අතර සෑම අයිතමයක්ම නිශ්චිත දේපල අගයන් අනුව වර්ග කිරීමට අවශ්‍යය.

පහත දැක්වෙන අරාව සැලකිල්ලට ගන්න,

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

අනුව වර්ග කළ විට name, බවට පත්විය යුතුය

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

1
පිළිතුර කියවා operator.itemgetter දෙස බලන්න . එකම ක්‍රියාවලියේදී මට බහුවිධ අගයන් වර්ග කළ හැකිද (නිදසුනක් ලෙස අප සතුව ඇති [{'name':'Bart', 'age':10, 'note':3},{'name':'Homer','age':10,'note':2},{'name':'Vasile','age':20,'note':3}] අතර භාවිතා කිරීමට: from operator import itemgetter newlist = sorted(old_list, key=itemgetter(-'note','name') සංස්කරණය කරන්න: පරීක්‍ෂා කර ඇති අතර එය ක්‍රියාත්මක වන නමුත් DESC සහ ASC යන නම සටහන් කරන්නේ කෙසේදැයි මම නොදනිමි.
ක්ලෝඩියු

Answers:


2495

එය cmp වෙනුවට යතුරක් භාවිතයෙන් පිරිසිදු බවක් පෙනේ:

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

හෝ JFSebastian සහ වෙනත් අය යෝජනා කළ පරිදි,

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

සම්පූර්ණත්වය සඳහා (fitzgeraldsteele විසින් අදහස් දක්වා ඇති පරිදි), බැසයාම reverse=Trueවර්ග කිරීමට එකතු කරන්න

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

34
යතුර භාවිතා කිරීම වඩා පිරිසිදු පමණක් නොව වඩාත් කාර්යක්ෂම වේ.
jfs

5
වේගවත්ම ක්‍රමය වනුයේ newlist.reverse () ප්‍රකාශයක් එක් කිරීමයි. එසේ නොමැතිනම් ඔබට cmp = lambda x, y: - cmp (x ['name'], y ['name']) වැනි සංසන්දනයක් අර්ථ දැක්විය හැකිය.
මාරියෝ එෆ්

3
වර්ග කිරීමේ අගය සංඛ්‍යාවක් නම් ඔබට කිව හැක්කේ: lambda k: (k ['age'] * -1) ප්‍රතිලෝම වර්ග කිරීමක් ලබා ගැනීම සඳහා
Philluminati

2
වර්ග කිරීම සඳහා ටුපල් මූලද්‍රව්‍යයේ දර්ශකය itemgetter(i)කොතැනදැයි ඔබ භාවිතා කරන්නේ නම් මෙය ටුපල් ලැයිස්තුවකට ද අදාළ වේ i.
රේඩිකන්ඩ්

43
itemgetterතර්ක එකකට වඩා පිළිගනී: itemgetter(1,2,3)එය හරියට ටුපල් එකක් ලබා දෙන ශ්‍රිතයකි obj[1], obj[2], obj[3], එබැවින් ඔබට එය සංකීර්ණ ආකාරයේ කිරීමට භාවිතා කළ හැකිය.
බකුරියූ

170
import operator

ශබ්දකෝෂ ලැයිස්තුව යතුර = 'නම' අනුව වර්ග කිරීමට:

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

ශබ්ද = 'වයස' අනුව ශබ්ද කෝෂ ලැයිස්තුව වර්ග කිරීමට:

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

9
කෙසේ හෝ නම සහ වයස ඒකාබද්ධ කිරීමට? (SQL ORDER BY name, age?)
monojohnny

29
@monojohnny: ඔව්, යතුර නැවත ලබා දෙන්න key=lambda k: (k['name'], k['age']). (හෝ key=itemgetter('name', 'age')). tuples විසින් cmpසෑම මූලද්‍රව්‍යයක්ම සංසන්දනය කරනු ඇත. එය ලේවැකි දීප්තිමත් ය.
ක්ලෝඩියු

1
ප්‍රලේඛනය තුළ ( docs.python.org/2/tutorial/datastructures.html ) සඳහා වන විකල්ප keyතර්කය list.sort()විස්තර කර නැත. එය සොයා ගත හැකි ස්ථානයක් තිබේද?
ටීටීටී

2
TTTT: සහ මිතුරන් සඳහා පුස්තකාල ලියකියවිලි බලන්න list.
කෙවින්

66
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'])

... ලැම්බඩා යනු IMO, තේරුම් ගැනීමට වඩා පහසු ය operator.itemgetter, නමුත් YMMV ය.


52

ඔබට යතුරු කිහිපයකින් ලැයිස්තුව වර්ග කිරීමට අවශ්‍ය නම් ඔබට පහත සඳහන් දෑ කළ හැකිය:

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']))

සංසන්දනය කිරීම සඳහා අගයන් තනි නූල් නිරූපණයක් බවට පරිවර්තනය කිරීම මත රඳා පවතින බැවින් එය තරමක් අශෝභන ය, නමුත් එය negative ණාත්මක සංඛ්‍යා ඇතුළු සංඛ්‍යා සඳහා අපේක්ෂිත පරිදි ක්‍රියා කරයි (ඔබ සංඛ්‍යා භාවිතා කරන්නේ නම් ශුන්‍ය පෑඩින් සමඟ ඔබේ නූල නිසි ලෙස සංයුති කිරීමට අවශ්‍ය වුවද)


2
ස්ථායී වන ටයිම්සෝර්ට් භාවිතයෙන් වර්ග කර ඇති අතර, නිර්ණායක කිහිපයක් මත වර්ග කිරීම සඳහා ඔබට කිහිප වතාවක් වර්ග කළ හැකිය
njzk2

njzk2 ගේ ප්‍රකාශය මට ක්ෂණිකව පැහැදිලි නැති නිසා පහත සඳහන් දෑ මට හමු විය. ඔබට njzk2 යෝජනා කරන ආකාරයට දෙවරක් වර්ග කළ හැකිය, නැතහොත් ඉහළ පිළිතුරේ ඇති operator.itemgetter වෙත බහු තර්ක ඉදිරිපත් කරන්න. සබැඳිය: stackoverflow.com/questions/5212870/…
Permafacture

15
නූල් බවට පරිවර්තනය කිරීම අවශ්‍ය නොවේ. යතුර ලෙස ටුපල් එකක් ආපසු දෙන්න.
වින්ස්ටන් එවර්ට්

කිහිප වතාවක් වර්ග කිරීම හක්ක
wouter bolsterlee

මෙය මගේ භාවිත කේතය සඳහා අයිතමයට වඩා හොඳින් ක්‍රියා කරයි.
බිනෝයි එස් කුමාර්

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

අත්තනෝමතික අගයකින් වර්ග කිරීම සඳහා 'යතුර' භාවිතා කරන අතර 'අයිතමජෙටර්' එක් එක් අයිතමයේ 'නම' ගුණාංගයට එම අගය සකසයි.


27
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']) 


19

ඔබට අභිරුචි සංසන්දනාත්මක ශ්‍රිතයක් භාවිතා කළ හැකිය, නැතහොත් අභිරුචි වර්ග කිරීමේ යතුරක් ගණනය කරන ශ්‍රිතයක් තුළ ඔබට සමත් විය හැකිය. යතුර ගණනය කරනු ලබන්නේ එක් අයිතමයකට එක් වරක් පමණක් වන අතර එය සැසඳීමේ කාර්යය තවත් බොහෝ වාරයක් ලෙස හැඳින්වේ.

ඔබට එය මේ ආකාරයෙන් කළ හැකිය:

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'))

19

පර්ල් වෙතින් ෂ්වාට්සියානු පරිවර්තනය භාවිතා කරමින්,

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'}]

පර්ල් ෂ්වාට්සියානු පරිවර්තනය පිළිබඳ තවත්

පරිගණක විද්‍යාවේදී, ෂ්වාට්සියානු පරිණාමනය යනු අයිතම ලැයිස්තුවක් වර්ග කිරීමේ කාර්යක්ෂමතාව වැඩි දියුණු කිරීම සඳහා භාවිතා කරන පර්ල් ක්‍රමලේඛන මෝඩකමකි. මූලද්‍රව්‍යවල නිශ්චිත දේපලක (යතුර) ඇණවුම මත ඇණවුම සැබවින්ම පදනම් වූ විට සංසන්දනය මත පදනම් වූ වර්ග කිරීම සඳහා මෙම මෝඩය සුදුසු වේ, එහිදී එම දේපල ගණනය කිරීම අවම වාර ගණනක් සිදු කළ යුතු දැඩි මෙහෙයුමක් වේ. ෂ්වාට්සියානු පරිවර්තනය සැලකිය යුතු කරුණක් වන්නේ එය නම් කරන ලද තාවකාලික අරා භාවිතා නොකිරීමයි.


9
Python මීට උදාහරණ සහයෝගය දී key=සඳහා .sort2.4 සිට, එම වසරේ 2004 වන අතර, එය Schwartzian එම තෝරා බේරා ගැනීමේ කේතය ඇ සී පරිණාමනය වන්නේ; එබැවින් මෙම ක්‍රමය ප්‍රයෝජනවත් වන්නේ පයිතන් 2.0-2.3 මත පමණි. මේ සියල්ලම අවුරුදු 12 ට වඩා පැරණි ය.
ඇන්ටි හාපාල


12

සමහර විට අපි 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}]

11

මෙන්න විකල්ප පොදු විසඳුම - එය යතුරු සහ අගයන් අනුව ඩික්ට්හි මූලද්‍රව්‍ය වර්ග කරයි. එහි ඇති වාසිය - යතුරු නියම කිරීමට අවශ්‍ය නොවන අතර සමහර ශබ්දකෝෂවල යතුරු නොමැති නම් එය තවමත් ක්‍රියාත්මක වේ.

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)

10

පැන්ඩාස් පැකේජය භාවිතා කිරීම තවත් ක්‍රමයකි, එය ක්‍රියාත්මක වන වේලාව අනෙක් අය විසින් යෝජනා කරන ලද සාම්ප්‍රදායික ක්‍රමවලට වඩා මන්දගාමී වේ:

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 +) නියෝග ලැයිස්තුවක් මෙන්න:

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

3
මම ඔබේ කේතය ධාවනය කර කාලරාමුවෙහි වැරැද්දක් සොයා ගතිමි. විශාල ක්‍රම පැන්ඩස් සඳහා ටයිමර් තර්ක කරයි: ඔබ "setup_small" සඳහන් කරන්නේ එය "setup_large" විය යුතු තැනයි. එම තර්කය වෙනස් කිරීම නිසා වැඩසටහන අවසන් නොවී ක්‍රියාත්මක වූ අතර මිනිත්තු 5 කට වඩා පසුව මම එය නැවැත්වුවෙමි. මම එය "ටයිමිට් (1)" සමඟ ධාවනය කරන විට, විශාල ක්‍රමවේදය පැන්ඩා තත්පර 7.3 කින් අවසන් කළ අතර එය එල්සී හෝ එල්සී 2 ට වඩා නරක ය.
clp2

ඔබ හරි, එය මගේ පැත්තෙන් තරමක් අධීක්ෂණයක්. විශාල නඩු සඳහා මම එය තවදුරටත් නිර්දේශ නොකරමි! මම පිළිතුර සංස්කරණය කර ඇත්තේ එය හැකියාවක් ලෙස සරලව ඉඩ දීම සඳහාය, භාවිත නඩුව තවමත් විවාදයට ලක්ව ඇත.
abby sobh

6

ඔබ මුල් අවශ්ය නොවේ නම් 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}]

6

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

මෙය පරීක්ෂා කරන්න .


4

මම පෙරහන් w / lambda හි විශාල රසිකයෙක් වී ඇති නමුත් ඔබ කාලය සංකීර්ණ බව සලකන්නේ නම් එය හොඳම විකල්පය නොවේ

පළමු විකල්පය

sorted_list = sorted(list_to_sort, key= lambda x: x['name'])
# returns list of values

දෙවන විකල්පය

list_to_sort.sort(key=operator.itemgetter('name'))
#edits the list, does not return a new list

ක්‍රියාත්මක වන වේලාවන් වේගයෙන් සංසන්දනය කිරීම

# First option
python3.6 -m timeit -s "list_to_sort = [{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}, {'name':'Faaa', 'age':57}, {'name':'Errr', 'age':20}]" -s "sorted_l=[]" "sorted_l = sorted(list_to_sort, key=lambda e: e['name'])"

ලූප 1000000 ක්, හොඳම ලූපයකට 3: 0.736 usec

# Second option 
python3.6 -m timeit -s "list_to_sort = [{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}, {'name':'Faaa', 'age':57}, {'name':'Errr', 'age':20}]" -s "sorted_l=[]" -s "import operator" "list_to_sort.sort(key=operator.itemgetter('name'))"

ලූප 1000000 ක්, හොඳම ලූපයකට 3: 0.438 usec


3

කාර්ය සාධනය සැලකිලිමත් වන්නේ නම්, අතින් සාදන ලද කාර්යයන්ට වඩා වේගයෙන් ගොඩනංවන ලද කාර්යයන් operator.itemgetterවෙනුවට මම භාවිතා කරමි lambda. මෙම itemgetterකාර්යය ආසන්න වශයෙන් 20% ක් වඩා වේගයෙන් සිදු කිරීමට පෙනේ lambdaමගේ පරීක්ෂණ මත පදනම්.

Https://wiki.python.org/moin/PythonSpeed වෙතින් :

ඒ හා සමානව, බිල්ඩින් කාර්යයන් අතින් සාදන ලද සමානකම් වලට වඩා වේගයෙන් ක්‍රියාත්මක වේ. උදාහරණයක් ලෙස, සිතියම (operator.add, v1, v2) සිතියමට වඩා වේගවත්ය (lambda x, y: x + y, v1, v2).

මෙහි භාවිතා වේගය තෝරා බේරා ගැනීමේ අතර සැසඳීමකි lambdaඑදිරිව itemgetter.

import random
import operator

# create a list of 100 dicts with random 8-letter names and random ages from 0 to 100.
l = [{'name': ''.join(random.choices(string.ascii_lowercase, k=8)), 'age': random.randint(0, 100)} for i in range(100)]

# Test the performance with a lambda function sorting on name
%timeit sorted(l, key=lambda x: x['name'])
13 µs ± 388 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

# Test the performance with itemgetter sorting on name
%timeit sorted(l, key=operator.itemgetter('name'))
10.7 µs ± 38.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

# Check that each technique produces same sort order
sorted(l, key=lambda x: x['name']) == sorted(l, key=operator.itemgetter('name'))
True

මෙම ක්‍රම දෙකම එකම අනුපිළිවෙලින් ලැයිස්තුව වර්ග කරයි (කේත කොටසෙහි අවසාන ප්‍රකාශය ක්‍රියාත්මක කිරීමෙන් සත්‍යාපනය වේ) නමුත් එකක් ටිකක් වේගවත් වේ.


-1

ඔබට පහත කේතය භාවිතා කළ හැකිය

sorted_dct = sorted(dct_name.items(), key = lambda x : x[1])
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.