Comparison of values in list of tuples in python 3.x

1

My question is how can I interact with this list in order to make comparisons between values.

def trocar(vals, posX, posY):
    temp = vals[posX]
    vals[posX] = vals[posY]
    vals[posY] = temp
    return None


def ordenar(valores):
    tamanho = len(valores) - 1
    troquei = True
    while troquei:
       troquei = False
       for i in range(tamanho):
          if valores[i] > valores[i + 1]:
            trocar(valores, i, i + 1)
            troquei = True
    tamanho -= 1
return valores


lista= [('Ana', 30, 6.69), ('João', 25, 6.11), ('Pedro', 30, 6.69),    ('Maria', 28, 5.45), ('Thiago', 40, 5.45), ('Raquel', 26, 10.0)]

x=ordenar(lista)
print(x) # [('Ana', 30, 6.69), ('João', 25, 6.11), ('Maria', 28, 5.45), ('Pedro', 30, 6.69), ('Raquel', 26, 10.0), ('Thiago', 40, 5.45)]

My intention is to print the names in order according to the values:

  • The first order is by average.
  • If one of the averages is the same step for age
  • If average and age are the same as alphabetical order of names
  • In the code above only one of the objectives has been achieved; get the names in alphabetical order

        
    asked by anonymous 08.04.2018 / 06:55

    1 answer

    3

    In your example a list of tuples is being sorted. In current logic you are using the > operator to compare two tuples. This makes sense since a tuple is a string, and conforms - Python documentation :

      

    Sequences are compared lexicographically by comparing matching elements. Collections that support order comparisons are sorted according to their first unequal elements (for example, [1,2,x] <= [1,2,y] has the same value as x <= y ).

    Knowing this, the trick to sort a list of tuples correctly is to rearrange the elements of each tuple according to your comparison criteria. In this case, you want to transform a tuple (nome, idade, media) into a tuple (media, idade, nome ) for comparison purposes.

    Assuming that the averages should be sorted in descending order and the other elements in ascending order the implementation would look like this:

    def rearranjar_tupla(tupla):
        return (-tupla[2], tupla[1], tupla[0])
    
    def ordenar(valores):
        tamanho = len(valores) - 1
        troquei = True
        while troquei:
           troquei = False
           for i in range(tamanho):
              if rearranjar_tupla(valores[i]) > rearranjar_tupla(valores[i + 1]):
                trocar(valores, i, i + 1)
                troquei = True
        tamanho -= 1
        return valores 
    

    See working on Ideone

    If averages must also be sorted in ascending order, simply reverse the tuple positions with extended slice :

    def rearranjar_tupla(tupla):
        return tupla[::-1]
    

    See working on Ideone

    It is important to note, however, that in addition to learning purposes, reinventing the wheel is often not a good idea. In addition to the extra code, this basic sorting algorithm (Bubble Sort) is expensive from the point of view of Asymptotic Complexity ( O (n²) ) and very poor from the point of view cache hits and memory management (multiple copies and unnecessary swaps put pressure on the Garbage Collector ).

    The Python standard API ordering engines rely on a fairly robust algorithm called

    Timsort , able to efficiently sort collections with Asymptotic Complexity > in the worst case.

    Using the standard Python library, we can replace all of the code in the first example with a single line of code:

    lista.sort(key=lambda x: (-x[2], x[1], x[0]))
    

    See working on Ideone

    Sources

  • SOen - How does tuple compare work in Python?
  • The Python Language Reference - Value comparisons
  • What's New in Python 2.3 - Extended Slices
  • Sorting HOW TO
  • Wikipedia - Timsort
  • 09.04.2018 / 00:54