¿Hay una línea conveniente para generar una lista de números y sus contrapartes negativas en Python?
Por ejemplo, digamos que quiero generar una lista con los números 6 a 9 y -6 a -9.
Mi enfoque actual es:
l = [x for x in range(6,10)]
l += [-x for x in l]
Un simple "one-liner" sería:
l = [x for x in range(6,10)] + [y for y in range(-9, -5)]
Sin embargo, generar dos listas y luego unirlas parece inconveniente.
python
python-3.x
upe
fuente
fuente
scalar or array-like, shape
estaría bien.Respuestas:
No estoy seguro de si el orden es importante, pero podría crear una tupla y descomprimirla en una lista de comprensión.
fuente
Crea una función agradable y legible:
Uso:
Así es como obtienes una línea conveniente para cualquier cosa. Evita tratar de parecer un hacker profesional mágico.
fuente
y
asignedValue
. Para mí, el valor agregado real del enfoque de definir una función sería entregar resultados en el orden estricto que la pregunta formulada (positiva, luego negativa) mientras se evita el problema de la línea única de Barmarchain
en la que los argumentos numéricos ligeramente diferentes tienen ser codificado en dos ocasiones.list
lo que sea). Después de años de tratar de codificar la mejor manera de tomar estas decisiones, el único principio general que tiene sentido para mí : si hay un buen nombre obvio para dar a algo en el programa, aproveche la oportunidad para hacerlo (y las funciones son una de las formas en que lo hacemos).Yo diría que la solución más simple es descomprimir dos rangos en una lista usando el
*
operador de desempaquetado:No solo es la respuesta más corta propuesta hasta ahora, sino que también es la más eficaz, ya que solo construye una lista única y no involucra llamadas de función más allá de las dos
range
s.Verifiqué esto probando todas las respuestas de esta pregunta usando el
timeit
módulo:(Pruebas de timeit realizadas con Python 3.6.9 en mi propia computadora (especificaciones promedio))
fuente
[*range(x, y), *range(-y + 1, -x + 1)]
Puede usar
itertools.chain()
para concatenar los dos rangos.fuente
Puedes usar
itertools.product
, que es el producto cartesiano.Esto podría ser más lento porque usa la multiplicación, pero debería ser fácil de leer.
Si desea una solución puramente funcional, también puede importar
itertools.starmap
yoperator.mul
:Sin embargo, esto es menos legible.
fuente
product
,starmap
yopertaor.mul
innecesariamente obtuso en comparación con las comprensiones de listas anidadas, pero apruebo la sugerencia de usar la multiplicación.[x * sign for sign in (1, -1) for x in range(6, 10)]
es solo un 10% más lento que[y for x in range(6, 10) for y in (x, -x)]
, y en casos donde el orden importa, más de 3 veces más rápido que ordenar el enfoque basado en tuplas.starmap
ymul
debería evitarse, pero creoproduct
que lo hace más legible, ya que agrupa los iteradores y sus elementos por separado. Los bucles dobles en la comprensión de la lista también pueden ser confusos, debido a su orden inesperado.Estás muy cerca, combinando dos
range
objetos. Pero hay una manera más fácil de hacerlo:Es decir, convierta cada
range
objeto en una lista y luego concatene las dos listas.Otro enfoque, usando itertools:
itertools.chain()
es como un generalizado+
: en lugar de agregar dos listas, encadena un iterador tras otro para hacer un "súper iterador". Luego pase esolist()
y obtendrá una lista concreta, con todos los números que desee en la memoria.fuente
[x for x in ...]
se escribe mejorlist(...)
.Pesando con otra posibilidad más.
Si desea legibilidad, su línea original era bastante buena, pero cambiaría los rangos para que sean los mismos, ya que creo que los límites negativos hacen que las cosas sean menos claras.
fuente
En mi opinión, el enfoque que se
itertools.chain
presenta en un par de otras respuestas es definitivamente el más claro de los proporcionados hasta ahora.Sin embargo, dado que en su caso el orden de los valores no importa , puede evitar tener que definir dos
range
objetos explícitos y, por lo tanto, evitar hacer todos los cálculos matemáticos necesarios para larange
indexación negativa , utilizandoitertools.chain.from_iterable
:Un poco detallado, pero lo suficientemente legible.
Otra opción similar es utilizar el desempaquetado de tuplas / argumentos con plain
chain
:Más conciso, pero creo que desempacar las tuplas es más difícil de asimilar en un escaneo rápido.
fuente
Esta es una variación de un tema (ver @Derte trdelník 's respuesta ) siguiendo la filosofía de
itertools
dondeLa idea es que, mientras definimos una nueva función, también podríamos hacerla genérica:
y aplicarlo a un
range
iterador particular :fuente
Si desea mantener el orden que ha especificado, puede utilizar el generador de rango incorporado de Python con un condicional:
Lo que te da la salida:
Y también funciona con 0 como inicio para el rango completo.
fuente
start
.Puede haber diferentes formas de hacer el trabajo.
Variables dadas: 1. inicio = 6 2. parada = 10
Puede probar esto también, para un enfoque diferente:
fuente
Me gustan las simetrías.
a = 6 b = 10
nums = [x + y para x en (- (a + b-1), 0) para y en rango (a, b)]
El resultado debe ser -9, -8, ..., 8, 9.
Creo que la expresión nums se puede mejorar, lo que sigue "en" y "rango" todavía no me parece equilibrado.
fuente