Extraiga el primer elemento de cada sublista en Python

6 minutos de lectura

avatar de usuario de konrad
Konrad

Me pregunto cuál es la mejor manera de extraer el primer elemento de cada sublista en una lista de listas y agregarlo a una nueva lista. Entonces si tengo:

lst = [[a,b,c], [1,2,3], [x,y,z]]

Y quiero sacar a, 1 y x y crear una lista separada de esos.

Lo intenté:

lst2.append(x[0] for x in lst)

  • Su código es casi correcto. El único problema es el uso de la lista de comprensión.

    – Abhishek Mittal

    31 de julio de 2014 a las 3:30

  • Consulte también stackoverflow.com/questions/25082410/… para ver un problema y una solución más generales.

    – Karl Knechtel

    15 de septiembre de 2021 a las 2:20

Usando lista de comprensión:

>>> lst = [['a','b','c'], [1,2,3], ['x','y','z']]
>>> lst2 = [item[0] for item in lst]
>>> lst2
['a', 1, 'x']

  • El método de comprensión de listas también es el más rápido, incluso más rápido que el método Numpy. La respuesta de jboi habla sobre la comparación de rendimiento,

    –Qiao Zhang

    16 de julio de 2018 a las 3:22

  • @QiaoZhang: numpy es más lento si tiene que convertir a un numpy matriz en primer lugar. Si los datos se almacenan como un numpy matriz desde el primer momento, será mucho más rápido.

    – ShadowRanger

    15 de septiembre de 2021 a las 2:30

avatar de usuario de dawg
perro

Podrías usar zip:

>>> lst=[[1,2,3],[11,12,13],[21,22,23]]
>>> zip(*lst)[0]
(1, 11, 21)

O, Python 3 donde zip no produce una lista:

>>> list(zip(*lst))[0]
(1, 11, 21)

O,

>>> next(zip(*lst))
(1, 11, 21)

O, (mi favorito) use numpy:

>>> import numpy as np
>>> a=np.array([[1,2,3],[11,12,13],[21,22,23]])
>>> a
array([[ 1,  2,  3],
       [11, 12, 13],
       [21, 22, 23]])
>>> a[:,0]
array([ 1, 11, 21])

  • No he votado a la baja, pero el primer fragmento de código (el zip) produce: “el objeto ‘zip’ no se puede suscribir”. Python 3.6 en Jupyter.

    – jboi

    7 de enero de 2018 a las 12:19

  • @jboi: Solo envuelve list rodearlo primero o usar next. Gracias

    – perro

    7 de enero de 2018 a las 15:32

Tuve el mismo problema y sentí curiosidad por el rendimiento de cada solución.

Aquí está el %timeit:

import numpy as np
lst = [['a','b','c'], [1,2,3], ['x','y','z']]

La primera forma numérica, transformando la matriz:

%timeit list(np.array(lst).T[0])
4.9 µs ± 163 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

Completamente nativo utilizando la comprensión de listas (como lo explica @alecxe):

%timeit [item[0] for item in lst]
379 ns ± 23.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Otra forma nativa de usar zip (como lo explica @dawg):

%timeit list(zip(*lst))[0]
585 ns ± 7.26 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Segunda forma numérica. También explicado por @dawg:

%timeit list(np.array(lst)[:,0])
4.95 µs ± 179 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

Sorprendentemente (bueno, al menos para mí) la forma nativa de usar la comprensión de listas es la más rápida y aproximadamente 10 veces más rápida que la forma numpy. Ejecutar las dos formas numpy sin la final list ahorra alrededor de un µs que todavía está en la diferencia de 10x.

Tenga en cuenta que, cuando rodeé cada fragmento de código con una llamada a lenpara garantizar que los generadores funcionen hasta el final, el tiempo se mantuvo igual.

  • hay una sobrecarga sustancial al crear una matriz.

    – hpaulj

    28 de agosto de 2018 a las 3:12

  • de acuerdo con hpaulj, si comienzas con una matriz numpy, [:,0] es más rápido. Pruébalo: lst = np.array([[‘a’,’b’,’c’], [1,2,3], [‘x’,’y’,’z’]]), luego lst[:,0]. La conversión en las pruebas de tiempo de ejemplo le da a la comprensión de la lista una ventaja injusta. Entonces, si puede, use una matriz numpy para almacenar sus datos si la velocidad es su objetivo final. Numpy es casi siempre más rápido. Está construido para la velocidad.

    – polvo espacial

    14/11/2018 a las 20:13


  • Gracias por compartir. tengo curiosidad por %timeit, ¿es esto algo mágico de python? Quiero decir %timeit no es python estándar, ¿no? ¡Gracias!

    – Dan.py

    23 de noviembre de 2022 a las 16:05

Avatar de usuario de Christian Abbott
cristiano abbot

Python incluye una función llamada itemgetter para devolver el elemento en un índice específico en una lista:

from operator import itemgetter

Pase a la función itemgetter() el índice del elemento que desea recuperar. Para recuperar el primer elemento, usaría itemgetter(0). Lo importante que hay que entender es que itemgetter(0) devuelve una función. Si pasa una lista a esa función, obtiene el elemento específico:

itemgetter(0)([10, 20, 30]) # Returns 10

Esto es útil cuando lo combina con map(), que toma una función como primer argumento y una lista (o cualquier otra iterable) como segundo argumento. Devuelve el resultado de llamar a la función en cada objeto en el iterable:

my_list = [['a', 'b', 'c'], [1, 2, 3], ['x', 'y', 'z']]
list(map(itemgetter(0), my_list)) # Returns ['a', 1, 'x']

Tenga en cuenta que map() devuelve un generador, por lo que el resultado se pasa a list() para obtener una lista real. En resumen, su tarea podría hacerse así:

lst2.append(list(map(itemgetter(0), lst)))

Este es un método alternativo al uso de una lista de comprensión, y qué método elegir depende en gran medida del contexto, la legibilidad y la preferencia.

Más información:
https://docs.python.org/3/library/operator.html#operator.itemgetter

Su código es casi correcto. El único problema es el uso de la lista de comprensión.

Si usas como: (x[0] para x en lst), devuelve un objeto generador. Si usas como: [x[0] for x in lst], devuelve una lista.

Cuando agrega la salida de comprensión de lista a una lista, la salida de comprensión de lista es el único elemento de la lista.

lst = [["a","b","c"], [1,2,3], ["x","y","z"]]
lst2 = []
lst2.append([x[0] for x in lst])
print lst2[0]

lst2 = [[‘a’, 1, ‘x’]]

lst2[0] = [‘a’, 1, ‘x’]

Por favor, hágamelo saber si estoy equivocado.

avatar de usuario de m00am
m00am

lst = [['a','b','c'], [1,2,3], ['x','y','z']]
outputlist = []
for values in lst:
    outputlist.append(values[0])

print(outputlist) 

Producción: ['a', 1, 'x']

Avatar de usuario de Hendrik
Hendrik

Usted dijo que tiene una lista existente. Así que iré con eso.

>>> lst1 = [['a','b','c'], [1,2,3], ['x','y','z']]
>>> lst2 = [1, 2, 3]

En este momento, está agregando el objeto generador a su segunda lista.

>>> lst2.append(item[0] for item in lst)
>>> lst2
[1, 2, 3, <generator object <genexpr> at 0xb74b3554>]

Pero probablemente quieras que sea una lista de los primeros elementos

>>> lst2.append([item[0] for item in lst])
>>> lst2
[1, 2, 3, ['a', 1, 'x']]

Ahora agregamos la lista de los primeros elementos a la lista existente. Si desea agregar los elementos mismos, no una lista de ellos, a los existentes, usaría list.extend. En ese caso, no tenemos que preocuparnos por agregar un generador, porque extend usará ese generador para agregar cada elemento que obtenga de allí, para extender la lista actual.

>>> lst2.extend(item[0] for item in lst)
>>> lst2
[1, 2, 3, 'a', 1, 'x']

o

>>> lst2 + [x[0] for x in lst]
[1, 2, 3, 'a', 1, 'x']
>>> lst2
[1, 2, 3]

https://docs.python.org/3.4/tutorial/datastructures.html#more-on-lists
https://docs.python.org/3.4/tutorial/datastructures.html#list-comprehensions

  • Tu respuesta es buena y completa para lo que suena como quiere el OP, pero creo que la palabra append en la pregunta está causando confusión. Parece que él/ella simplemente quiere la parte de comprensión de la lista de su solución.

    – beroe

    31 de julio de 2014 a las 6:21

¿Ha sido útil esta solución?