Pytanie Python 2.5 słownik 2 sortowanie kluczem


Mam słownik 200 000 pozycji (klucze są ciągami, a wartości są liczbami całkowitymi).

Jaki jest najlepszy / najbardziej pytonowy sposób drukowania elementów posortowanych według malejącej wartości, a następnie klucza rosnąco (tj. Sortowania z 2 klawiszami)?

 a={ 'keyC':1, 'keyB':2, 'keyA':1 }
b = a.items()
b.sort( key=lambda a:a[0])
b.sort( key=lambda a:a[1], reverse=True )
print b
>>>[('keyB', 2), ('keyA', 1), ('keyC', 1)]

14
2017-10-01 12:50


pochodzenie


Zobacz moją odpowiedź na powiązane pytanie tutaj. - hughdbrown


Odpowiedzi:


Nie możesz sortować słowników. Musisz posortować listę przedmiotów.

Poprzednie wersje były błędne. Gdy masz wartość liczbową, sortowanie jest łatwe w odwrotnej kolejności. Ci to zrobią. Ale to nie jest ogólne. Działa to tylko dlatego, że wartość jest numeryczna.

a = { 'key':1, 'another':2, 'key2':1 }

b= a.items()
b.sort( key=lambda a:(-a[1],a[0]) )
print b

Oto alternatywa, wykorzystująca jawną funkcję zamiast lambda i cmp zamiast opcji klucza.

def valueKeyCmp( a, b ):
    return cmp( (-a[1], a[0]), (-b[1], b[0] ) )

b.sort( cmp= valueKeyCmp )
print b

Bardziej ogólne rozwiązanie to w rzeczywistości dwa oddzielne rodzaje

b.sort( key=lambda a:a[1], reverse=True )
b.sort( key=lambda a:a[0] )
print b

17
2017-10-01 12:56



Dziękuję, ale to nie odnosi się do porządku sortowania ani 2 kluczowych cech tego rodzaju.
Tak. Wyszedłem na to. Przepraszam. Naprawione z poprawkami. - S.Lott
Trzeci przykład nie powoduje sortowania kluczem 2, a drugi sortowania usuwa pierwszy - Ricardo Reyes
@Ricardo Reyes: sortowanie python jest stabilnym sortem. Podczas sortowania najpierw na mniejszych klawiszach uzyskuje się końcowy wynik. - tzot
@Ricardo Reyes: docs.python.org/lib/typesseq-mutable.html - S.Lott


data = { 'keyC':1, 'keyB':2, 'keyA':1 }

for key, value in sorted(data.items(), key=lambda x: (-1*x[1], x[0])):
    print key, value

6
2017-10-01 14:11



Jest to najbardziej pythonic rozwiązanie moim zdaniem i najłatwiejsze do zrozumienia. - Jesse Shieh
Sortuje według wartości, nie klucza. - Nikola Kotur


Najbardziej pytającym sposobem na zrobienie tego byłoby poznanie trochę więcej informacji na temat rzeczywistych danych - konkretnie maksymalnej wartości, jaką możesz mieć - i zrobienie tego w ten sposób:

def sortkey((k, v)): 
    return (maxval - v, k)

items = thedict.items()
items.sort(key=sortkey)

ale jeśli nie znasz już maksymalnej wartości, poszukiwanie wartości maksymalnej oznacza zapętlenie przez dyktowanie dodatkowego czasu (z max(thedict.itervalues())), które mogą być drogie. Alternatywnie, wersja oprogramowania S.Lott w wersji KeyFunc:

def sortkey((k, v)): 
    return (-v, k)

items = thedict.items()
items.sort(key=sortkey)

Alternatywą, która nie dba o typy, byłaby funkcja porównania:

def sortcmp((ak, av), (bk, bv)):
    # compare values 'in reverse'  
    r = cmp(bv, av)
    if not r:
        # and then keys normally
        r = cmp(ak, bk)
    return r

items = thedict.items()
items.sort(cmp=sortcmp) 

i to rozwiązanie działa właściwie dla każdego rodzaju klucza i wartości, które chcesz mieszać w rosnącym i malejącym sortowaniu za pomocą tego samego klucza. Jeśli cenisz zwięzłość, możesz napisać sortcmp jako:

def sortcmp((ak, av), (bk, bv)):
    return cmp((bk, av), (ak, bv))

1
2017-10-01 13:00



Znajomość maksymalnej wartości jest bezużyteczna; użyj dowolnej wartości jako wartości maksymalnej. 0 przychodzi na myśl natychmiastowo, jak zasugerował S.Lott. ;) - tzot


Możesz użyć czegoś takiego:

dic = {'aaa':1, 'aab':3, 'aaf':3, 'aac':2, 'aad':2, 'aae':4}

def sort_compare(a, b):
    c = cmp(dic[b], dic[a])
    if c != 0:
        return c
    return cmp(a, b)

for k in sorted(dic.keys(), cmp=sort_compare):
    print k, dic[k]

Nie wiem jak to jest pythonic :)


0
2017-10-01 13:08





Wykorzystując rozwiązania Thomasa Woutersa i Ricardo Reyesa:

def combine(*cmps):
    """Sequence comparisons."""
    def comparator(a, b):
        for cmp in cmps:
            result = cmp(a, b):
            if result:
                return result
        return 0
    return comparator

def reverse(cmp):
    """Invert a comparison."""
    def comparator(a, b):
        return cmp(b, a)
    return comparator

def compare_nth(cmp, n):
    """Compare the n'th item from two sequences."""
    def comparator(a, b):
        return cmp(a[n], b[n])
    return comparator

rev_val_key_cmp = combine(
        # compare values, decreasing
        reverse(compare_nth(1, cmp)),

        # compare keys, increasing
        compare_nth(0, cmp)
    )

data = { 'keyC':1, 'keyB':2, 'keyA':1 }

for key, value in sorted(data.items(), cmp=rev_val_key_cmp):
    print key, value

0
2017-10-01 14:53





>>> keys = sorted(a, key=lambda k: (-a[k], k))

lub

>>> keys = sorted(a)
>>> keys.sort(key=a.get, reverse=True)

następnie

print [(key, a[key]) for key in keys]
[('keyB', 2), ('keyA', 1), ('keyC', 1)]

0
2017-11-11 04:43