Define criteria for sorting a list of lists

Asked

Viewed 193 times

4

I have a list of lists of strings. For example a list, in which the internal lists have size n=3:

listEx =  [['verde','preto','laraja'], ['rosa','lilás','azul'], ['bordô','cinza','branco'], [preto, roxo, amarelo]]

If I want to sort the list listEx, defining as criterion the position 0 of the inner lists I do:

 lista = sorted(listEx, key = lambda x: x[0])

But what I want is to define a tiebreaker. Therefore, if there are two lists with equal elements at position 0, the tiebreaker criterion should be position 1. If the tie still persists, take position 2 as the tiebreaker criterion. The same goes for the position n.

The impasse is that n is variable. That is, depending on the instance of the problem, the internal lists have different cardinalities. However, I guarantee there will be no lists of different sizes.

Maybe there’s something in Python like qsort of the C language, where I create a function compara_elementos, can define my criteria in code form.

  • That? https://answall.com/q/347634/101

2 answers

4


One way is to create an "old-fashioned comparison function" (used in Python 2), which takes 2 elements and returns a negative number if the first is "less", a positive number if the first is "greater", or zero if they are "equal".

Then you use functools.cmp_to_key, which converts this comparison function to a key Function, compatible with sorted:

def compare(list1, list2):
    for e1, e2 in zip(list1, list2):
        if e1 != e2:
            return 1 if e1 > e2 else -1
    return 0

import functools

listEx =  [
  ['verde','preto','laraja'],
  ['rosa','lilás','azul'],
  ['bordô','cinza','branco'],
  ['preto', 'roxo', 'amarelo'],
  ['azul', 'vermelho', 'roxo'],
  ['azul', 'vermelho', 'cinza']
]    
lista = sorted(listEx, key = functools.cmp_to_key(compare))
print(lista)

I use zip to go through the lists at the same time, and I compare their elements (detail that zip It will stop when the shortest list is finished, but as you ensure that they all have the same size, this is not a concern). If all elements are equal, I return 0. If they are different, I return the respective result (-1 if the former is smaller, 1 if it is larger).

The result is:

[['azul', 'vermelho', 'cinza'], ['azul', 'vermelho', 'roxo'], ['bordô', 'cinza', 'branco'], ['preto', 'roxo', 'amarelo'], ['rosa', 'lilás', 'azul'], ['verde', 'preto', 'laraja']]

-1

One way to perform this comparison is to join the internal list elements into a single string before comparing. This ordering will only be valid if the tiebreaker is alphabetical, so when the first two elements are blue, it compares the next elements alphabetically.

listEx =  [['cinza', 'roxo','amarelo'], ['azul','laranja','verde'],['bordô','cinza','branco'],  ['azul','amarelo','preto'], ['azul','amarelo','verde']]
cores_ordenadas = sorted(listEx, key = lambda x: str().join((x)))
print(cores_ordenadas)

Exit:

[['azul', 'amarelo', 'preto'],
 ['azul', 'amarelo', 'verde'],
 ['azul', 'laranja', 'verde'], 
 ['bordô', 'cinza', 'branco'], 
 ['cinza', 'roxo', 'amarelo']]

Browser other questions tagged

You are not signed in. Login or sign up in order to post.