tuple - unire due liste python




Come ordinare(lista/tupla) di liste/tuple? (7)

Ho alcuni dati in una lista di liste o in una lista di tuple, come questa:

data = [[1,2,3], [4,5,6], [7,8,9]]
data = [(1,2,3), (4,5,6), (7,8,9)]

E voglio ordinare il secondo elemento nel sottoinsieme. Significa, ordinando per 2,5,8 dove 2 è da (1,2,3), 5 è da (4,5,6). Qual è il modo comune per farlo? Devo memorizzare tuple o liste nella mia lista?


La risposta di @Stephen è al punto! Ecco un esempio per una migliore visualizzazione,

Gridare per i fan di Ready Player One! =)

>>> gunters = [('2044-04-05', 'parzival'), ('2044-04-07', 'aech'), ('2044-04-06', 'art3mis')]
>>> gunters.sort(key=lambda tup: tup[0])
>>> print gunters
[('2044-04-05', 'parzival'), ('2044-04-06', 'art3mis'), ('2044-04-07', 'aech')]

key è una funzione che verrà chiamata per trasformare gli elementi della collezione per il confronto .. come il metodo compareTo in Java.

Il parametro passato alla chiave deve essere qualcosa che può essere richiamato. Qui, l'uso di lambda crea una funzione anonima (che è un chiamabile).
La sintassi di lambda è la parola lambda seguita da un nome iterabile quindi da un singolo blocco di codice.

Sotto l'esempio, stiamo ordinando una lista di tuple che contiene il tempo di abt delle informazioni di determinati eventi e il nome dell'attore.

Stiamo ordinando questo elenco per volta dell'occorrenza dell'evento, che è l'elemento 0 di una tupla.

Nota: s.sort([cmp[, key[, reverse]]]) ordina gli elementi di s in posizione


Ordinare una tupla è abbastanza semplice:

tuple(sorted(t))

Per ordinare una lista di tuple (<word>, <count>) , per count in ordine decrescente e word in ordine alfabetico:

data = [
('betty', 1),
('bought', 1),
('a', 1),
('bit', 1),
('of', 1),
('butter', 2),
('but', 1),
('the', 1),
('was', 1),
('bitter', 1)]

Io uso questo metodo:

sorted(data, key=lambda tup:(-tup[1], tup[0]))

e mi dà il risultato:

[('butter', 2),
('a', 1),
('betty', 1),
('bit', 1),
('bitter', 1),
('bought', 1),
('but', 1),
('of', 1),
('the', 1),
('was', 1)]

Senza lambda:

def sec_elem(s):
    return s[1] 
sorted(data, key=sec_elem) 

La risposta di Stephen è quella che userei. Per completezza, ecco il pattern DSU (decorare-ordina-non-decorato) con le list comprehension:

decorated = [(tup[1], tup) for tup in data]
decorated.sort()
undecorated = [tup for second, tup in decorated]

O, più tersamente:

[b for a,b in sorted((tup[1], tup) for tup in data)]

Come notato nel Python Sorting HowTo , questo non è più necessario da Python 2.4, quando le funzioni chiave sono diventate disponibili.


itemgetter() è leggermente più veloce di lambda tup: tup[1] , ma l'aumento è relativamente modesto (circa dal 10 al 25 percento).

(Sessione IPython)

>>> from operator import itemgetter
>>> from numpy.random import randint
>>> values = randint(0, 9, 30000).reshape((10000,3))
>>> tpls = [tuple(values[i,:]) for i in range(len(values))]

>>> tpls[:5]    # display sample from list
[(1, 0, 0), 
 (8, 5, 5), 
 (5, 4, 0), 
 (5, 7, 7), 
 (4, 2, 1)]

>>> sorted(tpls[:5], key=itemgetter(1))    # example sort
[(1, 0, 0), 
 (4, 2, 1), 
 (5, 4, 0), 
 (8, 5, 5), 
 (5, 7, 7)]

>>> %timeit sorted(tpls, key=itemgetter(1))
100 loops, best of 3: 4.89 ms per loop

>>> %timeit sorted(tpls, key=lambda tup: tup[1])
100 loops, best of 3: 6.39 ms per loop

>>> %timeit sorted(tpls, key=(itemgetter(1,0)))
100 loops, best of 3: 16.1 ms per loop

>>> %timeit sorted(tpls, key=lambda tup: (tup[1], tup[0]))
100 loops, best of 3: 17.1 ms per loop

sorted_by_second = sorted(data, key=lambda tup: tup[1])

o:

data.sort(key=lambda tup: tup[1])  # sorts in place




tuples