데이터베이스의 두 필드(문자열 필드와 숫자 필드)에서 읽은 값 사전이 있습니다. 문자열 필드는 고유하므로 사전의 키입니다.
키를 기준으로 정렬할 수 있지만 값을 기준으로 정렬하려면 어떻게 해야 합니까?
참고: 여기에서 스택 오버플로 질문을 읽었습니다 . 사전 값으로 사전 목록을 정렬하려면 어떻게 합니까? 그리고 아마도 사전 목록을 갖도록 내 코드를 변경할 수 있지만 사전 목록이 실제로 필요하지 않기 때문에 오름차순 또는 내림차순으로 정렬하는 더 간단한 솔루션이 있는지 알고 싶었습니다.
파이썬 3.7 이상 또는 CPython 3.6
Dict는 Python 3.7 이상에서 삽입 순서를 유지합니다. CPython 3.6에서도 동일하지만 구현 세부 사항 입니다.
>>> x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0} >>> {k: v for k, v in sorted(x.items(), key=lambda item: item[1])} {0: 0, 2: 1, 1: 2, 4: 3, 3: 4}
음, 실제로 "사전 값으로 정렬"하는 것이 가능합니다. 최근에 나는 Code Golf(스택 오버플로 질문 코드 골프: 단어 빈도 차트 )에서 그렇게 해야 했습니다. 요약하자면 문제는 다음과 같은 종류였습니다. 텍스트가 주어지면 각 단어가 얼마나 자주 나타나는지 세고 빈도가 감소하는 순서로 정렬된 상위 단어 목록을 표시합니다.
단어를 키로 사용하고 각 단어의 발생 횟수를 값으로 사용하여 사전을 구성하면 다음과 같이 단순화됩니다.
from collections import defaultdict d = defaultdict(int) for w in text.split(): d[w] += 1
sorted(d, key=d.get) 를 사용하여 사용 빈도에 따라 정렬된 단어 목록을 얻을 수 있습니다. 정렬은 단어 발생 횟수를 정렬 키로 사용하여 사전 키를 반복합니다.
for w in sorted(d, key=d.get, reverse=True): print(w, d[w])
나는 사람들이 "나는 키로 쉽게 사전을 정렬할 수 있지만 값으로 정렬하는 방법"이 무엇을 의미하는지 설명하기 위해 이 자세한 설명을 작성합니다. 그리고 원래 게시물은 그러한 문제를 해결하려고 했던 것 같습니다. 그리고 해결책은 위와 같이 값을 기반으로 일종의 키 목록을 수행하는 것입니다.
Nas Banov
다음을 사용할 수 있습니다.
sorted(d.items(), key=lambda x: x[1])
이렇게 하면 사전 내의 각 항목 값을 기준으로 사전을 가장 작은 것에서 가장 큰 것 순으로 정렬합니다.
이것이 첫 번째 단계로 얇은 레이어 OrderedDict 구현으로 이어지기를 바랍니다. @JimFasarakis-Hilliard가 지적했듯이 일부는 향후 OrderedDict 유형의 사용 사례도 볼 수 있습니다. 나는 파이썬 커뮤니티 전체가 이것이 시간의 시험을 견딜 수 있는지, 그리고 다음 단계가 무엇인지 신중하게 검사할 것이라고 생각합니다.
다음의 안정적인 순서로 열린 가능성을 놓치지 않기 위해 코딩 습관을 재고할 시간입니다.
키워드 인수 및
(중간) 딕셔너리 저장
첫 번째는 경우에 따라 함수 및 메서드 구현 시 디스패치를 쉽게 해주기 때문입니다.
두 번째는 처리 파이프라인에서 중간 저장소로 dict 를 더 쉽게 사용하도록 권장하기 때문입니다.
그리고 아마도 꽤 많은 스택 오버플로 장식 질문 및 답변 페이지가 이 정보의 변형을 받을 것이며 많은 고품질 답변에도 버전별 업데이트가 필요할 것입니다.
주의 사항 Emptor(하지만 아래 업데이트 2017-12-15 참조):
@ajcr은 "이 새로운 구현의 순서 보존 측면은 구현 세부 사항으로 간주되며 의존해서는 안 됩니다."라고 적법하게 언급했습니다. ( whatsnew36 에서 ) 니트 따기가 아니라 인용이 약간 비관적으로 잘렸습니다 ;-). "(앞으로 변경될 수 있지만 현재 및 미래의 모든 Python 구현에 대한 순서 보존 의미론을 명령하기 위해 언어 사양을 변경하기 전에 몇 가지 릴리스의 언어에서 이 새로운 dict 구현을 갖는 것이 바람직합니다. 임의의 반복 순서가 여전히 유효한 언어의 이전 버전(예: Python 3.5)과의 하위 호환성을 유지하는 데 도움이 됩니다."
따라서 일부 인간 언어(예: 독일어)에서와 같이 사용법이 언어를 형성하고 이제 ... whatsnew36 에서 의지가 선언되었습니다.
따라서 dict 삽입 순서의 버전 3.6 CPython 부작용은 이제 언어 사양의 일부가 되었습니다(더 이상 구현 세부 사항이 아님). collections.OrderedDict 대한 몇 가지 구별되는 디자인 목표를 표면화했습니다. Raymond Hettinger가 토론 중에 상기시켰습니다.
Dilettant
나는 같은 문제가 있었고 다음과 같이 해결했습니다.
WantedOutput = sorted(MyDict, key=lambda x : MyDict[x])
("딕셔너리를 정렬할 수 없습니다"라고 답한 사람은 질문을 읽지 않았습니다! 실제로 "키를 기준으로 정렬할 수 있지만 값을 기준으로 정렬하려면 어떻게 해야 하나요?" 키 값에 따라 정렬됩니다.)
순서가 잘 정의되어 있지 않다는 점에 유의하십시오(같은 값을 가진 키는 출력 목록에서 임의의 순서로 표시됩니다).
from django.utils.datastructures import SortedDict def sortedDictByKey(self,data): """Sorted dictionary order by key""" sortedDict = SortedDict() if data: if isinstance(data, dict): sortedKey = sorted(data.keys()) for k in sortedKey: sortedDict[k] = data[k] return sortedDict
Argun
물론 일반 Python 사전은 원래 순서를 유지하지 않기 때문에 OrderedDict 를 사용해야 함을 기억하십시오.
from collections import OrderedDict a = OrderedDict(sorted(originalDict.items(), key=lambda x: x[1]))
Python 2.7 이상이 없는 경우 가장 좋은 방법은 생성기 함수의 값을 반복하는 것입니다. (AN 있습니다 OrderedDict 2.4 및 2.6은 여기에 있지만,
) 나는 그것이 얼마나 잘 작동하는지 모른다
그리고
b) 당연히 다운받아 설치해야 합니다. 관리자 권한이 없는 경우 옵션이 없을 수 있습니다.)
def gen(originalDict): for x, y in sorted(zip(originalDict.keys(), originalDict.values()), key=lambda z: z[1]): yield (x, y) #Yields as a tuple with (key, value). You can iterate with conditional clauses to get what you want. for bleh, meh in gen(myDict): if bleh == "foo": print(myDict[bleh])
모든 값을 인쇄할 수도 있습니다.
for bleh, meh in gen(myDict): print(bleh, meh)
Python 3.0 이상을 사용하지 않는 경우 인쇄 후 괄호를 제거하는 것을 잊지 마십시오.
ytpillai
Dilettant가 지적했듯이 Python 3.6은 이제 순서를 유지합니다 ! 나는 iterable(tuple, list, dict)의 정렬을 용이하게 하는 내가 작성한 함수를 공유할 것이라고 생각했습니다. 후자의 경우 키 또는 값을 기준으로 정렬할 수 있으며 숫자 비교를 고려할 수 있습니다. >= 3.6에만 해당!
예를 들어 문자열과 int를 포함하는 iterable에서 sorted를 사용하려고 하면 sorted()가 실패합니다. 물론 str()을 사용하여 문자열 비교를 강제할 수 있습니다. 1220 보다 작은 실제 숫자 비교를 수행하려고 합니다(문자열 비교에서는 그렇지 않음). 그래서 나는 다음을 생각해 냈습니다. 명시적 숫자 비교를 원할 때 모든 값을 부동 소수점으로 변환하려고 시도하여 명시적 숫자 정렬을 시도하는 num_as_num 성공하면 숫자 정렬을 수행하고, 그렇지 않으면 문자열 비교에 의존합니다.
개선을 위한 의견을 환영합니다.
def sort_iterable(iterable, sort_on=None, reverse=False, num_as_num=False): def _sort(i): # sort by 0 = keys, 1 values, None for lists and tuples try: if num_as_num: if i is None: _sorted = sorted(iterable, key=lambda v: float(v), reverse=reverse) else: _sorted = dict(sorted(iterable.items(), key=lambda v: float(v[i]), reverse=reverse)) else: raise TypeError except (TypeError, ValueError): if i is None: _sorted = sorted(iterable, key=lambda v: str(v), reverse=reverse) else: _sorted = dict(sorted(iterable.items(), key=lambda v: str(v[i]), reverse=reverse)) return _sorted if isinstance(iterable, list): sorted_list = _sort(None) return sorted_list elif isinstance(iterable, tuple): sorted_list = tuple(_sort(None)) return sorted_list elif isinstance(iterable, dict): if sort_on == 'keys': sorted_dict = _sort(0) return sorted_dict elif sort_on == 'values': sorted_dict = _sort(1) return sorted_dict elif sort_on is not None: raise ValueError(f"Unexpected value {sort_on} for sort_on. When sorting a dict, use key or values") else: raise TypeError(f"Unexpected type {type(iterable)} for iterable. Expected a list, tuple, or dict")
#Assume dictionary to be: d = {'apple': 500.1, 'banana': 1500.2, 'orange': 1.0, 'pineapple': 789.0} # create a temporary list tmp = [] # iterate through the dictionary and append each tuple into the temporary list for key, value in d.items(): tmptuple = (value, key) tmp.append(tmptuple) # sort the list in ascending order tmp = sorted(tmp) print (tmp)
목록을 내림차순으로 정렬하려면 원래 정렬 라인을 다음과 같이 변경하면 됩니다.
tmp = sorted(tmp, reverse=True)
목록 이해를 사용하면 하나의 라이너는 다음과 같습니다.
#Assuming the dictionary looks like d = {'apple': 500.1, 'banana': 1500.2, 'orange': 1.0, 'pineapple': 789.0} #One liner for sorting in ascending order print (sorted([(v, k) for k, v in d.items()])) #One liner for sorting in descending order print (sorted([(v, k) for k, v in d.items()], reverse=True))
샘플 출력:
#Asending order [(1.0, 'orange'), (500.1, 'apple'), (789.0, 'pineapple'), (1500.2, 'banana')] #Descending order [(1500.2, 'banana'), (789.0, 'pineapple'), (500.1, 'apple'), (1.0, 'orange')]
mcgag
dict를 반복하고 값을 기준으로 내림차순으로 정렬합니다.
$ python --version Python 3.2.2 $ cat sort_dict_by_val_desc.py dictionary = dict(siis = 1, sana = 2, joka = 3, tuli = 4, aina = 5) for word in sorted(dictionary, key=dictionary.get, reverse=True): print(word, dictionary[word]) $ python sort_dict_by_val_desc.py aina 5 tuli 4 joka 3 sana 2 siis 1
juhoh
값이 정수이고 Python 2.7 이상을 사용하는 경우 dictcollections.Counter 를 사용할 수 있습니다. most_common 메소드는 값을 기준으로 정렬된 모든 항목을 제공합니다.
months = {"January": 31, "February": 28, "March": 31, "April": 30, "May": 31, "June": 30, "July": 31, "August": 31, "September": 30, "October": 31, "November": 30, "December": 31} def mykey(t): """ Customize your sorting logic using this function. The parameter to this function is a tuple. Comment/uncomment the return statements to test different logics. """ return t[1] # sort by number of days in the month #return t[1], t[0] # sort by number of days, then by month name #return len(t[0]) # sort by length of month name #return t[0][-1] # sort by last character of month name # Since a dictionary can't be sorted by value, what you can do is to convert # it into a list of tuples with tuple length 2. # You can then do custom sorts by passing your own function to sorted(). months_as_list = sorted(months.items(), key=mykey, reverse=False) for month in months_as_list: print month