First sort the list with the longest items

I use lambda to change the sort behavior.

sorted(list, key=lambda item:(item.lower(),len(item)))

Sort the list containing items A1,A2,A3,A,B1,B2,B3,B, result A,A1,A2,A3,B,B1,B2,B3.

My expected sorted list will be A1,A2,A3,A,B1,B2,B3,B.

I already tried turning it on len(item)for sorting, which didn't work. How to change lambda so that there is a sort result instead?

+4
source share
4 answers

Here is one way to do this:

>>> import functools
>>> def cmp(s, t):
    'Alter lexicographic sort order to make longer keys go *before* any of their prefixes'
    ls, lt = len(s), len(t)
    if ls < lt:   s += t[ls:] + 'x'
    elif lt < ls: t += s[lt:] + 'x'
    if s < t: return -1
    if s > t: return 1
    return 0

>>> sorted(l, key=functools.cmp_to_key(cmp))
['A1', 'A2', 'A3', 'A', 'B1', 'B2', 'B3', 'B']

Traditionally, the lexicographic sort order is longer than the lines after their identical identical prefixes (i.e., 'abc' goes before 'abcd').

, "" , , :

compare abc to defg     -->  compare abcgx to defg
compare a   to a2       -->  compare a2x to a2

functools.cmp_to_key() .

, .

FWIW, , :

def cmp(s, t):
    'Alter lexicographic sort order to make longer keys go *before* any of their prefixes'
    for p, q in zip(s, t):
        if p < q: return -1
        if q < p: return 1
    if len(s) > len(t): return -1
    elif len(t) > len(s): return 1
    return 0

:

  • , .
  • .
  • , .
  • , .
+5

: len, .

sorted(list, key=lambda item:(item.lower(),-len(item)))   # doesn't work!

, - . Alpha . , .

. .

: , chr(127) ( char , ASCII) , : .

l = ["A","B","A1","A2","A3","B1","B2","B3"]

maxlen = max(len(x) for x in l)
print(sorted(l, key=lambda item:item.lower()+chr(127)*(maxlen-len(item))))

:

['A1', 'A2', 'A3', 'A', 'B1', 'B2', 'B3', 'B']

BTW list .

+1

, :

:

>>> L = ['A1', 'B2', 'A', 'A2', 'B1', 'A3', 'B3', 'B']
>>> print(sorted(L, key = lambda item: (item[0], -len(item), item)))
['A1', 'A2', 'A3', 'A', 'B1', 'B2', 'B3', 'B']
0

I like Tries, so just for fun I wrote a solution based on Trie:

class Trie():

    def __init__(self):
        self.data = {}

    def add(self, word):
        ref = self.data
        for char in word:
            ref[char] = char in ref and ref[char] or {}
            ref = ref[char]
        ref[''] = 1


def sorted_print(dct, prefix=''):
    sorted_keys = sorted(filter(bool, dct.keys()), key=str.lower)
    for key in sorted_keys:
        v = dct[key]
        if isinstance(v, dict):
            sorted_print(v, prefix + key)
    if '' in dct:
        print(prefix)

my_list = ["B1", "B3", "B2", "A1", "A2", "A3", "A", "B"]
t = Trie()
for w in my_list:
    t.add(w)


sorted_print(t.data)
# A1
# A2
# A3
# A
# B1
# B2
# B3
# B

This should work for any string of any length.

Please note that the result is simply printed on the screen, and not written to a new list. You haven't written much code, so I'll leave it as an exercise;)

0
source

Source: https://habr.com/ru/post/1672707/


All Articles