여러 키로 개체를 정렬하는 방법은 무엇입니까?
또는 실제로 사전 목록을 여러 키로 정렬하려면 어떻게 해야 합니까?
받아쓰기 목록이 있습니다.
b = [{u'TOT_PTS_Misc': u'Utley, Alex', u'Total_Points': 96.0},
{u'TOT_PTS_Misc': u'Russo, Brandon', u'Total_Points': 96.0},
{u'TOT_PTS_Misc': u'Chappell, Justin', u'Total_Points': 96.0},
{u'TOT_PTS_Misc': u'Foster, Toney', u'Total_Points': 80.0},
{u'TOT_PTS_Misc': u'Lawson, Roman', u'Total_Points': 80.0},
{u'TOT_PTS_Misc': u'Lempke, Sam', u'Total_Points': 80.0},
{u'TOT_PTS_Misc': u'Gnezda, Alex', u'Total_Points': 78.0},
{u'TOT_PTS_Misc': u'Kirks, Damien', u'Total_Points': 78.0},
{u'TOT_PTS_Misc': u'Worden, Tom', u'Total_Points': 78.0},
{u'TOT_PTS_Misc': u'Korecz, Mike', u'Total_Points': 78.0},
{u'TOT_PTS_Misc': u'Swartz, Brian', u'Total_Points': 66.0},
{u'TOT_PTS_Misc': u'Burgess, Randy', u'Total_Points': 66.0},
{u'TOT_PTS_Misc': u'Smugala, Ryan', u'Total_Points': 66.0},
{u'TOT_PTS_Misc': u'Harmon, Gary', u'Total_Points': 66.0},
{u'TOT_PTS_Misc': u'Blasinsky, Scott', u'Total_Points': 60.0},
{u'TOT_PTS_Misc': u'Carter III, Laymon', u'Total_Points': 60.0},
{u'TOT_PTS_Misc': u'Coleman, Johnathan', u'Total_Points': 60.0},
{u'TOT_PTS_Misc': u'Venditti, Nick', u'Total_Points': 60.0},
{u'TOT_PTS_Misc': u'Blackwell, Devon', u'Total_Points': 60.0},
{u'TOT_PTS_Misc': u'Kovach, Alex', u'Total_Points': 60.0},
{u'TOT_PTS_Misc': u'Bolden, Antonio', u'Total_Points': 60.0},
{u'TOT_PTS_Misc': u'Smith, Ryan', u'Total_Points': 60.0}]
그리고 Total_Points로 역순으로 된 다중 키 정렬을 사용해야 합니다.TOT_PTS_Misc
.
이 작업은 명령 프롬프트에서 다음과 같이 수행할 수 있습니다.
a = sorted(b, key=lambda d: (-d['Total_Points'], d['TOT_PTS_Misc']))
하지만 저는 목록과 정렬 키를 전달하는 기능을 통해 이것을 실행해야 합니다.예를들면,def multikeysort(dict_list, sortkeys):
.
멀티키 정렬 기능에 전달되는 임의의 수의 키에 대해 목록을 정렬하고 정렬 키에 임의의 수의 키가 있을 수 있으며 역 정렬이 필요한 키는 앞에 '-'로 식별된다는 점을 고려하는 람다 라인을 사용할 수 있는 방법은 무엇입니까?
이 기사는 이를 위한 다양한 기술에 대한 개요를 제공합니다.요구사항이 "전체 양방향 멀티키"보다 간단한 경우 확인하십시오.수락된 답변과 방금 참조한 블로그 게시물이 어떤 식으로든 서로에게 영향을 미쳤다는 것은 분명하지만, 어느 순서인지는 잘 모르겠습니다.
링크가 끊기는 경우 위에서 다루지 않은 예제의 매우 빠른 개요를 보여 줍니다.
mylist = sorted(mylist, key=itemgetter('name', 'age'))
mylist = sorted(mylist, key=lambda k: (k['name'].lower(), k['age']))
mylist = sorted(mylist, key=lambda k: (k['name'].lower(), -k['age']))
이 대답은 사전의 모든 열에 적용됩니다. 음수 열은 숫자일 필요가 없습니다.
def multikeysort(items, columns):
from operator import itemgetter
comparers = [((itemgetter(col[1:].strip()), -1) if col.startswith('-') else
(itemgetter(col.strip()), 1)) for col in columns]
def comparer(left, right):
for fn, mult in comparers:
result = cmp(fn(left), fn(right))
if result:
return mult * result
else:
return 0
return sorted(items, cmp=comparer)
다음과 같이 부를 수 있습니다.
b = [{u'TOT_PTS_Misc': u'Utley, Alex', u'Total_Points': 96.0},
{u'TOT_PTS_Misc': u'Russo, Brandon', u'Total_Points': 96.0},
{u'TOT_PTS_Misc': u'Chappell, Justin', u'Total_Points': 96.0},
{u'TOT_PTS_Misc': u'Foster, Toney', u'Total_Points': 80.0},
{u'TOT_PTS_Misc': u'Lawson, Roman', u'Total_Points': 80.0},
{u'TOT_PTS_Misc': u'Lempke, Sam', u'Total_Points': 80.0},
{u'TOT_PTS_Misc': u'Gnezda, Alex', u'Total_Points': 78.0},
{u'TOT_PTS_Misc': u'Kirks, Damien', u'Total_Points': 78.0},
{u'TOT_PTS_Misc': u'Worden, Tom', u'Total_Points': 78.0},
{u'TOT_PTS_Misc': u'Korecz, Mike', u'Total_Points': 78.0},
{u'TOT_PTS_Misc': u'Swartz, Brian', u'Total_Points': 66.0},
{u'TOT_PTS_Misc': u'Burgess, Randy', u'Total_Points': 66.0},
{u'TOT_PTS_Misc': u'Smugala, Ryan', u'Total_Points': 66.0},
{u'TOT_PTS_Misc': u'Harmon, Gary', u'Total_Points': 66.0},
{u'TOT_PTS_Misc': u'Blasinsky, Scott', u'Total_Points': 60.0},
{u'TOT_PTS_Misc': u'Carter III, Laymon', u'Total_Points': 60.0},
{u'TOT_PTS_Misc': u'Coleman, Johnathan', u'Total_Points': 60.0},
{u'TOT_PTS_Misc': u'Venditti, Nick', u'Total_Points': 60.0},
{u'TOT_PTS_Misc': u'Blackwell, Devon', u'Total_Points': 60.0},
{u'TOT_PTS_Misc': u'Kovach, Alex', u'Total_Points': 60.0},
{u'TOT_PTS_Misc': u'Bolden, Antonio', u'Total_Points': 60.0},
{u'TOT_PTS_Misc': u'Smith, Ryan', u'Total_Points': 60.0}]
a = multikeysort(b, ['-Total_Points', 'TOT_PTS_Misc'])
for item in a:
print item
두 열 중 하나를 사용하지 않고 사용해 보십시오.정렬 순서가 반대로 표시됩니다.
다음: 추가 클래스를 사용하지 않도록 변경합니다.
2016-01-17
이 답변에서 영감을 받아 반복 가능한 일치 조건에서 첫 번째 항목을 얻는 가장 좋은 방법은 무엇입니까?,코드를 줄였습니다.
from operator import itemgetter as i
def multikeysort(items, columns):
comparers = [
((i(col[1:].strip()), -1) if col.startswith('-') else (i(col.strip()), 1))
for col in columns
]
def comparer(left, right):
comparer_iter = (
cmp(fn(left), fn(right)) * mult
for fn, mult in comparers
)
return next((result for result in comparer_iter if result), 0)
return sorted(items, cmp=comparer)
당신이 당신의 코데서를 좋아한다면요.
이후 2016-01-17
이것은 python3와 함께 작동합니다(이것은 제거되었습니다).cmp
에 대한 주장.sort
):
from operator import itemgetter as i
from functools import cmp_to_key
def cmp(x, y):
"""
Replacement for built-in function cmp that was removed in Python 3
Compare the two objects x and y and return an integer according to
the outcome. The return value is negative if x < y, zero if x == y
and strictly positive if x > y.
https://portingguide.readthedocs.io/en/latest/comparisons.html#the-cmp-function
"""
return (x > y) - (x < y)
def multikeysort(items, columns):
comparers = [
((i(col[1:].strip()), -1) if col.startswith('-') else (i(col.strip()), 1))
for col in columns
]
def comparer(left, right):
comparer_iter = (
cmp(fn(left), fn(right)) * mult
for fn, mult in comparers
)
return next((result for result in comparer_iter if result), 0)
return sorted(items, key=cmp_to_key(comparer))
이 대답에서 영감을 얻은 파이썬 3에서 사용자 지정 정렬을 어떻게 해야 합니까?
이것이 꽤 오래된 질문이라는 것을 알지만, 파이썬이 다음과 같은 정렬 루틴에 대해 안정적인 정렬 순서를 보장한다고 언급하는 답변은 없습니다.list.sort()
그리고.sorted()
이는 동등하게 비교되는 항목이 원래 순서를 유지한다는 것을 의미합니다.
이것은 다음과 같은 것을 의미합니다.ORDER BY name ASC, age DESC
(SQL 표기법 사용) 사전 목록은 다음과 같이 수행할 수 있습니다.
items.sort(key=operator.itemgetter('age'), reverse=True)
items.sort(key=operator.itemgetter('name'))
항목이 "작은" 특성별로 처음 정렬되는 방법을 기록합니다.age
(계속됨), "주요" 속성으로name
올바른 최종 순서로 이어집니다.
반전/반전은 앞에 마이너스 기호를 붙여 부정할 수 있는 숫자뿐만 아니라 모든 주문 가능한 유형에 대해 작동합니다.
그리고 (적어도) CPython에서 사용되는 Timsort 알고리즘 때문에 실제로는 상당히 빠릅니다.
def sortkeypicker(keynames):
negate = set()
for i, k in enumerate(keynames):
if k[:1] == '-':
keynames[i] = k[1:]
negate.add(k[1:])
def getit(adict):
composite = [adict[k] for k in keynames]
for i, (k, v) in enumerate(zip(keynames, composite)):
if k in negate:
composite[i] = -v
return composite
return getit
a = sorted(b, key=sortkeypicker(['-Total_Points', 'TOT_PTS_Misc']))
오늘도 비슷한 문제가 있었습니다. 숫자 값을 내림차순으로, 문자열 값을 오름차순으로 사전 항목을 정렬해야 했습니다.방향이 충돌하는 문제를 해결하기 위해 정수 값을 부정했습니다.
OP에 적용 가능한 제 솔루션의 변형입니다.
sorted(b, key=lambda e: (-e['Total_Points'], e['TOT_PTS_Misc']))
매우 단순합니다. 그리고 매력적으로 작동합니다.
[{'TOT_PTS_Misc': 'Chappell, Justin', 'Total_Points': 96.0},
{'TOT_PTS_Misc': 'Russo, Brandon', 'Total_Points': 96.0},
{'TOT_PTS_Misc': 'Utley, Alex', 'Total_Points': 96.0},
{'TOT_PTS_Misc': 'Foster, Toney', 'Total_Points': 80.0},
{'TOT_PTS_Misc': 'Lawson, Roman', 'Total_Points': 80.0},
{'TOT_PTS_Misc': 'Lempke, Sam', 'Total_Points': 80.0},
{'TOT_PTS_Misc': 'Gnezda, Alex', 'Total_Points': 78.0},
{'TOT_PTS_Misc': 'Kirks, Damien', 'Total_Points': 78.0},
{'TOT_PTS_Misc': 'Korecz, Mike', 'Total_Points': 78.0},
{'TOT_PTS_Misc': 'Worden, Tom', 'Total_Points': 78.0},
{'TOT_PTS_Misc': 'Burgess, Randy', 'Total_Points': 66.0},
{'TOT_PTS_Misc': 'Harmon, Gary', 'Total_Points': 66.0},
{'TOT_PTS_Misc': 'Smugala, Ryan', 'Total_Points': 66.0},
{'TOT_PTS_Misc': 'Swartz, Brian', 'Total_Points': 66.0},
{'TOT_PTS_Misc': 'Blackwell, Devon', 'Total_Points': 60.0},
{'TOT_PTS_Misc': 'Blasinsky, Scott', 'Total_Points': 60.0},
{'TOT_PTS_Misc': 'Bolden, Antonio', 'Total_Points': 60.0},
{'TOT_PTS_Misc': 'Carter III, Laymon', 'Total_Points': 60.0},
{'TOT_PTS_Misc': 'Coleman, Johnathan', 'Total_Points': 60.0},
{'TOT_PTS_Misc': 'Kovach, Alex', 'Total_Points': 60.0},
{'TOT_PTS_Misc': 'Smith, Ryan', 'Total_Points': 60.0},
{'TOT_PTS_Misc': 'Venditti, Nick', 'Total_Points': 60.0}]
다음을 사용하여 여러 열의 2D 배열을 정렬합니다.
def k(a,b):
def _k(item):
return (item[a],item[b])
return _k
이것은 임의 개수의 항목에서 작동하도록 확장될 수 있습니다.저는 분류 가능한 키에 대한 더 나은 액세스 패턴을 찾는 것이 멋진 비교기를 쓰는 것보다 낫다고 생각하는 경향이 있습니다.
>>> data = [[0,1,2,3,4],[0,2,3,4,5],[1,0,2,3,4]]
>>> sorted(data, key=k(0,1))
[[0, 1, 2, 3, 4], [0, 2, 3, 4, 5], [1, 0, 2, 3, 4]]
>>> sorted(data, key=k(1,0))
[[1, 0, 2, 3, 4], [0, 1, 2, 3, 4], [0, 2, 3, 4, 5]]
>>> sorted(a, key=k(2,0))
[[0, 1, 2, 3, 4], [1, 0, 2, 3, 4], [0, 2, 3, 4, 5]]
from operator import itemgetter
from functools import partial
def _neg_itemgetter(key, d):
return -d[key]
def key_getter(key_expr):
keys = key_expr.split(",")
getters = []
for k in keys:
k = k.strip()
if k.startswith("-"):
getters.append(partial(_neg_itemgetter, k[1:]))
else:
getters.append(itemgetter(k))
def keyfunc(dct):
return [kg(dct) for kg in getters]
return keyfunc
def multikeysort(dict_list, sortkeys):
return sorted(dict_list, key = key_getter(sortkeys)
시연:
>>> multikeysort([{u'TOT_PTS_Misc': u'Utley, Alex', u'Total_Points': 60.0},
{u'TOT_PTS_Misc': u'Russo, Brandon', u'Total_Points': 96.0},
{u'TOT_PTS_Misc': u'Chappell, Justin', u'Total_Points': 96.0}],
"-Total_Points,TOT_PTS_Misc")
[{u'Total_Points': 96.0, u'TOT_PTS_Misc': u'Chappell, Justin'},
{u'Total_Points': 96.0, u'TOT_PTS_Misc': u'Russo, Brandon'},
{u'Total_Points': 60.0, u'TOT_PTS_Misc': u'Utley, Alex'}]
구문 분석은 약간 취약하지만 적어도 키 사이에 다양한 공간을 허용합니다.
람다는 이미 익숙하기 때문에, 여기 덜 자세한 해결책이 있습니다.
>>> def itemgetter(*names):
return lambda mapping: tuple(-mapping[name[1:]] if name.startswith('-') else mapping[name] for name in names)
>>> itemgetter('a', '-b')({'a': 1, 'b': 2})
(1, -2)
언급URL : https://stackoverflow.com/questions/1143671/how-to-sort-objects-by-multiple-keys
'sourcecode' 카테고리의 다른 글
Mac에서 bashrc 파일을 어디서 찾을 수 있습니까? (0) | 2023.07.22 |
---|---|
Oracle PL/SQL에서 테이블 루프 (0) | 2023.07.22 |
사전을 사용하여 matplotlib를 사용하여 막대 그림 그리기 (0) | 2023.07.22 |
조건이 충족되는 경우 Numpy 요소 교체 (0) | 2023.07.22 |
일부 행을 업데이트하는 동안 고유 키 무시(mariaDB) (0) | 2023.07.22 |