Sort lists in Python 3 depending on another list

1

Dear, I have several lists that depend on one another, for example in a list I have a code and in another I have the date of that code. My problem is that I had to add a new code list that still has its list of dates. My intention is to create a single list of chronologically ordered dates but keep the position with respect to your code list.

What I was doing was to paste the new list of dates and new code list at the end, leaving a single large list of codes and another large list of dates, like this:

    for i in range(len(codigo2)): #Union lista principal FDE, Fecha y Status
        CODIGOS.append(codigo2[i])
        FECHAS.append(fechas2[i])

But in doing this the chronological order is lost since I am only adding the new codes and dates at the end. They know a way to sort a list and keep those new positions for another list.

    
asked by Jorge Ponti 26.07.2017 в 20:55
source

4 answers

1

As I mentioned it is possible using the Schwartzian transform that although the idea comes from Perl in Python it can be implemented using zip .

The idea is simple, zip is used to obtain the pairs of elements and sorted is applied to them. This gives us a list with the pairs ordered by the first iterable past to zip (equal to this element, the following is used).

Once this is done, we unpack the list returned by sorted and pass all its elements as arguments to zip to get back two lists using the elements of the tuples. In Python you can unpack an iterable using * in front of it.

The only complicated thing is to understand the operation of zip , I think that with a couple of examples it can be clarified better than with words:

>>> a = (1, 2, 3, 4)
>>> b = ('a', 'b', 'c', 'd')
>>> c = list(zip(a, b))
>>> c
[(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')]
>>> d, e = zip(*c)
>>> d
(1, 2, 3, 4)
>>> e
('a', 'b', 'c', 'd')

zip(*c) is equivalent to:

zip((1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'))

An example of how to order using the previous idea based on your code:

from datetime import date

# Las dos listas originales
CODIGOS = [1, 2, 3, 4, 5]
FECHAS = [date(2017, 7, 24), date(2017, 7, 25), date(2017, 7, 26), date(2017, 7, 27), date(2017, 7, 28)]

# Concatenas nuevos valores
CODIGOS.extend([7, 10, 24, 14])
FECHAS.extend([date(2017, 7, 30), date(2017, 7, 20), date(2017, 8, 1), date(2017, 7, 21)])

# Ordenamos aplicando lo explicado antes
FECHAS, CODIGOS = map(list, zip(*sorted(zip(FECHAS, CODIGOS))))

Exit:

  

> > > DATES
  [datetime.date (2017, 7, 20), datetime.date (2017, 7, 21), datetime.date (2017, 7, 24), datetime.date (2017, 7, 25), datetime.date (2017) , 7, 26), datetime.date (2017, 7, 27), datetime.date (2017, 7, 28), datetime.date (2017, 7, 30), datetime.date (2017, 8, 1)]
  > > > CODES
  [10, 14, 1, 2, 3, 4, 5, 7, 24]

If you notice use list.extend to concatenate the lists, consider using this in your code instead of the cycle for and append that you use now.

    
answered by 26.07.2017 / 22:19
source
1

Defines a class Entrada

class Entrada:
    def __init__(codigo, fecha):
        self.codigo = codigo
        self.fecha = fecha

Then if you have two lists with entries you can mix them and arrange them as follows

entradas = [
    Entrada('code 1', 234567890),
    Entrada('code 2', 726578236),
    Entrada('code 3', 328957359)
]

entradas2 = [
    Entrada('code 4', 789275883),
    Entrada('code 5', 349092090),
    Entrada('code 6', 952893850)
]

for i in range(len(entradas2)):
    entradas.append(entradas2[i])

entradas.sort(key=lambda entrada: entrada.fecha)
    
answered by 26.07.2017 в 21:17
1

If the positions of both lists match, that is, the code in CODIGOS[x] corresponds to the date in FECHAS[x] , what you can do is use zip :

>>> codigos
[10, 20, 30, 40]
>>> fechas
[datetime.date(2017, 7, 15), datetime.date(2017, 7, 20), datetime.date(2017, 7, 1)]
>>> zip(codigos, fechas)
[(10, datetime.date(2017, 7, 15)), (20, datetime.date(2017, 7, 20)), (30, datetime.date(2017, 7, 1))]
    
answered by 26.07.2017 в 21:22
1

Jorge, the following code explains my comment and gives you a solution to your question. I agree with @FjSevilla, if you are already using pandas , why transform the data into lists and then do this ordering? pandas offers a lot of functionality to operate with dataframes , maybe you have to investigate on that side, but this can surely help you

codigo = [1, 2, 4]
fechas = ["2017-01-01", "2017-01-02", "2017-01-04"]

codigo2 = [3]
fechas2 = ["2017-01-03"]


print("Las dos listas con el orden natural y sincronizadas")
print("\n".join([str(e) for e in zip(codigo, fechas)]))

print("Agrego las listas nuevas")
print("\n".join([str(e) for e in zip(codigo2, fechas2)]))

fechas = fechas + fechas2
codigo = codigo + codigo2

print("El resultado sigue manteniendo el orden natural, sincronizadas, pero ahora la fecha esta desordenada")
print("\n".join([str(e) for e in zip(codigo, fechas)]))


print("Si ordeno la lista de fechas pierdo la sincronía con la de códigos")
fechas.sort()
print("\n".join([str(e) for e in zip(codigo, fechas)]))

print("Si armo tuplas (codigo,fecha) puedo ordenar sin problema por una de las columnas")
tuplelist = [e for e in zip(codigo, fechas)]
tuplelist.sort(key=lambda tuplelist: tuplelist[1])
print("\n".join([str(e) for e in tuplelist]))

This is the exit:

Las dos listas con el orden natural y sincronizadas
(1, '2017-01-01')
(2, '2017-01-02')
(4, '2017-01-04')
Agrego las listas nuevas
(3, '2017-01-03')
El resultado sigue manteniendo el orden natural, sincronizadas, pero ahora la fecha esta desordenada
(1, '2017-01-01')
(2, '2017-01-02')
(4, '2017-01-04')
(3, '2017-01-03')
Si ordeno la lista de fechas pierdo la sincronía con la de códigos
(1, '2017-01-01')
(2, '2017-01-02')
(4, '2017-01-03')
(3, '2017-01-04')
Si armo tuplas (codigo,fecha) puedo ordenar sin problema por una de las columnas
(1, '2017-01-01')
(2, '2017-01-02')
(4, '2017-01-03')
(3, '2017-01-04')

Note that each "code" corresponds to the day on the "date". When ordering the "date" we lost the "synchrony", it's like when you order by a column in Excel and forget to indicate the others. The solution is to maintain a data structure that allows "code" and "date" to be related. One possibility is to use the "tuples", with this: tuplelist = [e for e in zip(codigo, fechas)] transforms the two lists into another list of tuples, something like [(codigo, fecha), (codigo, fecha),...] . With this structure you can already do: tuplelist.sort(key=lambda tuplelist: tuplelist[1]) to sort everything by date (column 2). Finally, if you want to leave everything again like the original lists, you just have to do an "unzip":

codigo, fecha = [list(e) for e in zip(*tuplelist)]
    
answered by 26.07.2017 в 22:06