Sort list according to the value of the last two digits is repeated or not

2

It is possible to sort in python a list like this:

lista = ["0113", "0208", "0312", "0430", "0512", "0612", "0716", "0827", "0916"]

So, taking into account the last two digits of each element, compare them and group them if they have the same value. So that they are like this:

ListaNueva = ["0113", "0208", "0312", "0512", "0612", "0430",  "0716", "0916", "0827"]

The elements "0512" and "0612" in the list have been grouped behind "0312" since they had the same value as this one, 12.

"0916" would be placed behind the "0716" since they share the value of 16. The rest of the elements would not be modified since they do not have any element with the same value.

Thanks in advance.

    
asked by Arkaitz Ortega 21.10.2018 в 21:13
source

1 answer

0

You define partially an order for the case in which the last two figures are equal, because you do not indicate how to order the elements within that case (should it appear before 0512 or 0612? With what criteria?).

On the other hand, for the case in which the last two figures do not coincide, there is no ordering criterion. I am not sure if this indicates that it does not matter in which order it appears, or if on the contrary, the relative order in which they appeared in the original sequence should be specified.

There is a case with a very simple solution, and it is the one that I am going to solve in case it serves you. It is about considering the last two figures as if they were a month, so to speak, and the first two as if they were the day, so to speak, and then ordering all the elements in a "chronological" order (so to speak).

With this criterion, 0512 would go before 0612. But 0208 should move to the beginning of the list (since 08 would be the smallest "month").

This is implemented by providing sorted() with a function key that puts the last two characters of the string ahead, and let sorted do the rest. So:

sorted(lista, key=lambda x: x[-2:] + x[:-2])

Result:

['0208', '0312', '0512', '0612', '0113', '0716', '0916', '0827', '0430']

Update

The case in which you must preserve the original order of the elements that do not end the same is not really an order (the title of the question is equivocal), but rather a "grouping". We want to simply group, in the same order in which they appear in the list, the elements that end the same.

This can be done with a dictionary whose key is a two-digit string (ex: "12") and whose value is a list with all the elements that end up like this, in the order in which they appear. There will be elements of the dictionary (for example, the one with a "13" key) whose list would have a single element. We also want the dictionary to preserve the order in which we are inserting the keys, because it is the order in which we will find them in the original list.

A normal python dictionary does not preserve the order (unless you use python 3.6 or higher), but you can use a OrderedDict .

This would be the proposed solution:

from collections import OrderedDict

def ordena(l):
  # Primero creamos el diccionario con las agrupaciones
  grupos = OrderedDict()
  for dato in l:
    cifras_finales = dato[-2:]
    if cifras_finales in grupos:
      grupos[cifras_finales].append(dato)
    else:
      grupos[cifras_finales] = [dato]

  # Ahora usamos ese diccionario para crear la lista final a retornar
  resultado = []
  for v in grupos.values():
    resultado.extend(v)
  return resultado

ordena(lista)

Result:

['0113', '0208', '0312', '0512', '0612', '0430', '0716', '0916', '0827']
    
answered by 21.10.2018 / 21:31
source