Existe um one-liner conveniente para gerar uma lista de números e suas contrapartes negativas no Python?
Por exemplo, digamos que eu queira gerar uma lista com os números 6 a 9 e -6 a -9.
Minha abordagem atual é:
l = [x for x in range(6,10)]
l += [-x for x in l]
Um simples "one-liner" seria:
l = [x for x in range(6,10)] + [y for y in range(-9, -5)]
No entanto, gerar duas listas e juntá-las parece inconveniente.
python
python-3.x
upe
fonte
fonte
scalar or array-like, shape
seria bom.Respostas:
Não tenho certeza se o pedido é importante, mas você pode criar uma tupla e descompactá-la em uma lista de compreensão.
fonte
Crie uma função agradável e legível:
Uso:
É assim que você obtém uma linha conveniente para qualquer coisa. Evite tentar parecer um hacker profissional mágico.
fonte
y
parasignedValue
. Para mim, o verdadeiro valor agregado da abordagem de definir uma função seria fornecer resultados na ordem estrita que a pergunta solicitada (positiva, depois negativa), evitando o problema da linhachain
única de Barmar, na qual argumentos numéricos ligeiramente diferentes para ser codificado duas vezes.list
for.) Depois de anos tentando codificar a melhor maneira de tomar essas decisões, o único princípio geral que faz sentido para mim : se houver um nome óbvio e bom para dar a algo no programa, aproveite a oportunidade para fazê-lo (e as funções são uma das maneiras de fazer isso).Eu diria que a solução mais simples é descompactar dois intervalos em uma lista usando o
*
operador de descompactação:Além de ser a resposta mais curta proposta até agora, também é a que apresenta melhor desempenho, porque constrói apenas uma lista única e não envolve chamadas de função além dos dois
range
segundos.Eu verifiquei isso testando todas as respostas desta pergunta usando o
timeit
módulo:(timeit testado com o Python 3.6.9 no meu próprio computador (especificações médias))
fonte
[*range(x, y), *range(-y + 1, -x + 1)]
Você pode usar
itertools.chain()
para concatenar os dois intervalos.fonte
Você pode usar
itertools.product
, que é o produto cartesiano.Isso pode ser mais lento porque você usa a multiplicação, mas deve ser fácil de ler.
Se você deseja uma solução puramente funcional, também pode importar
itertools.starmap
eoperator.mul
:No entanto, isso é menos legível.
fonte
product
,starmap
eopertaor.mul
desnecessariamente obtuso em comparação com as compreensões de listas aninhadas, mas aprovo a sugestão de usar a multiplicação.[x * sign for sign in (1, -1) for x in range(6, 10)]
é apenas 10% mais lento que[y for x in range(6, 10) for y in (x, -x)]
e, nos casos em que a ordem é importante, mais de 3x mais rápido do que classificar a abordagem baseada em tupla.starmap
emul
deve ser evitado, mas eu acho queproduct
torna mais legível, uma vez que agrupa os iteradores e seus elementos separadamente. Loops duplos na compreensão da lista também podem ser confusos, devido à sua ordem inesperada.Você está realmente perto, combinando dois
range
objetos. Mas há uma maneira mais fácil de fazer isso:Ou seja, converta cada
range
objeto em uma lista e concatene as duas listas.Outra abordagem, usando itertools:
itertools.chain()
é como um generalizado+
: em vez de adicionar duas listas, ele liga um iterador após outro para criar um "super iterador". Depois passe isso paralist()
e você obterá uma lista concreta, com todos os números que deseja na memória.fonte
[x for x in ...]
é melhor escritolist(...)
.Pesando com mais uma possibilidade.
Se você deseja legibilidade, sua linha única original foi muito boa, mas eu alteraria os intervalos para os mesmos, pois acho que os limites negativos tornam as coisas menos claras.
fonte
A OMI, a abordagem utilizada
itertools.chain
apresentada em algumas outras respostas é definitivamente a mais limpa dentre as fornecidas até agora.No entanto, como no seu caso a ordem dos valores não importa , você pode evitar a definição de dois
range
objetos explícitos e, assim, evitar toda a matemática isolada necessária para arange
indexação negativa , usandoitertools.chain.from_iterable
:Um pouco detalhado, mas legível o suficiente.
Outra opção semelhante é usar a tupla / argumento descompactar com plain
chain
:Mais conciso, mas acho mais difícil descompactar as tuplas em uma verificação rápida.
fonte
Esta é uma variação de um tema (ver @Derte trdelník 's resposta ) seguindo a filosofia de
itertools
ondeA idéia é que, enquanto definimos uma nova função, também podemos torná-la genérica:
e aplique-o a um
range
iterador específico :fonte
Se você deseja manter a ordem que especificou, pode usar o gerador de alcance interno do Python com uma condição:
O que fornece a saída:
E também funciona com 0 como o início de toda a gama.
fonte
start
.Pode haver diferentes maneiras de fazer o trabalho.
Variáveis fornecidas: 1. start = 6 2. stop = 10
Você pode tentar isso também, para uma abordagem diferente:
fonte
Eu gosto de simetrias.
a = 6 b = 10
nums = [x + y para x em (- (a + b-1), 0) para y no intervalo (a, b)]
O resultado deve ser -9, -8, ..., 8, 9.
Eu acredito que a expressão nums pode ser melhorada, o que se segue "in" e "range" ainda me parece desequilibrado.
fonte