Eu sou um novato em python tentando alcançar o seguinte:
Eu tenho uma lista de listas:
lst = [[567,345,234],[253,465,756, 2345],[333,777,111, 555]]
Eu quero mapear em outra lista contendo apenas o segundo menor número de cada sublista. Portanto, o resultado deve ser:
[345, 465, 333]
Por exemplo, se eu estivesse interessado apenas no menor número, poderia fazer:
map(lambda x: min(x),lst)
Eu gostaria de poder fazer isso:
map(lambda x: sort(x)[1],lst)
mas a classificação não acorrenta. (retorna nenhum)
nem algo assim é permitido:
map(lambda x: sort(x); x[1],lst) #hence the multiple statement question
Existe uma maneira de fazer isso com map em python, mas sem definir uma função nomeada ? (é fácil com blocos anônimos em rubi, por exemplo)
lambda x: sort(x) OR x[1]
funcionaria: aqui o OR avalia seu primeiro argumento (valor de retorno Nenhum) como um bool (=> False) e, nesse caso, OR retorna seu segundo argumento. Mas, como dizem as respostas, é melhor evitar lambda.Respostas:
Há várias respostas diferentes que posso dar aqui, desde sua pergunta específica até questões mais gerais. Então, do mais específico ao mais geral:
P. Você pode colocar várias instruções em um lambda?
R. Não. Mas você realmente não precisa usar um lambda. Você pode colocar as instruções em um
def
. ie:P. Você pode obter o segundo item mais baixo de um lambda classificando a lista?
A. Sim. Como aponta a resposta de alex ,
sorted()
é uma versão do tipo que cria uma nova lista, em vez de classificação no local, e pode ser encadeada. Observe que provavelmente é isso que você deve usar - é uma má prática que seu mapa tenha efeitos colaterais na lista original.P. Como devo obter o segundo item mais baixo de cada lista em uma sequência de listas?
A.
sorted(l)[1]
não é realmente a melhor maneira para isso. Ele tem complexidade O (N log (N)), enquanto uma solução O (n) existe. Isso pode ser encontrado no módulo heapq.Então, basta usar:
Também é geralmente considerado mais claro usar uma compreensão de lista, o que evita o lambda por completo:
fonte
k
(como aqui com 'segundo mais baixo')O(k*log(n)+n)
simplifica paraO(n)
Colocar as declarações em uma lista pode simular várias declarações:
Por exemplo:
fonte
None
.Viajante do tempo aqui. Se você geralmente deseja ter várias instruções dentro de um lambda, pode passar outros lambdas como argumentos para esse lambda.
Na verdade, você não pode ter várias instruções, mas pode simular isso passando lambdas para lambdas.
Edit: O viajante do tempo retorna! Você também pode abusar do comportamento das expressões booleanas (tendo em mente as regras de curto-circuito e a veracidade) para as operações em cadeia. Usar o operador ternário oferece ainda mais potência. Novamente, você não pode ter várias instruções , mas é claro que pode ter muitas chamadas de função. Este exemplo faz algum lixo arbitrário com um monte de dados, mas mostra que você pode fazer algumas coisas engraçadas. As instruções de impressão são exemplos de funções que retornam
None
(assim como o.sort()
método), mas também ajudam a mostrar o que olambda
está fazendo.fonte
Use a função classificada , como esta:
fonte
[sorted(x)[1] for x in list_of_lists]
.Na verdade, você pode ter várias instruções em uma expressão lambda em python. Não é totalmente trivial, mas em seu exemplo, o seguinte funciona:
Você tem que se certificar de que cada instrução não retorne nada ou se a envolva (.. e False). O resultado é o que é retornado pela última avaliação.
Exemplo:
fonte
Usando begin () a partir daqui: http://www.reddit.com/r/Python/comments/hms4z/ask_pyreddit_if_you_were_making_your_own/c1wycci
fonte
Uma maneira Hacky de combinar várias instruções em uma única instrução em python é usar a palavra-chave "e" como um operador de curto-circuito. Em seguida, você pode usar essa única instrução diretamente como parte da expressão lambda.
Isso é semelhante a usar "&&" como o operador de curto-circuito em linguagens shell, como o bash.
Observe também: você sempre pode corrigir uma instrução de função para retornar um valor verdadeiro, envolvendo a função.
Exemplo:
Pensando bem, provavelmente é melhor usar 'ou' em vez de 'e', pois muitas funções retornam '0' ou Nenhum em caso de sucesso. Então você pode se livrar da função de wrapper no exemplo acima:
Operar 'e' avaliará as expressões até chegar ao primeiro valor de retorno zero. após o qual ele entra em curto-circuito. 1 e 1 e 0 e 1 avalia: 1 e 1 e 0, e cai 1
'or' operator irá avaliar as expressões até chegar ao primeiro valor de retorno diferente de zero. após o qual ele entra em curto-circuito.
0 ou 0 ou 1 ou 0 avalia 0 ou 0 ou 1 e descarta 0
fonte
Ou se você quiser evitar lambda e ter um gerador em vez de uma lista:
(classificado (col) [1] para col em lst)
fonte
Deixe-me apresentar a você um hack glorioso, mas assustador:
Agora você pode usar este
LET
formulário da seguinte forma:que dá:
[345, 465, 333]
fonte
Você pode fazer isso em tempo O (n) usando min e index em vez de sort ou heapq.
Primeiro crie uma nova lista de tudo, exceto o valor mínimo da lista original:
Em seguida, pegue o valor mínimo da nova lista:
Agora todos juntos em um único lambda:
Sim, é realmente feio, mas deve ser algoritmicamente barato. Além disso, uma vez que algumas pessoas neste tópico desejam ver as compreensões de lista:
fonte
Isso é exatamente o que a
bind
função em uma Mônada é usada.Com a
bind
função, você pode combinar vários lambda em um lambda, cada lambda representando uma instrução.fonte
Na verdade, existe uma maneira de usar várias instruções em lambda. Esta é minha solução:
fonte
exec
não pode ser introspectado por um IDE inteligenteSim. Você pode defini-lo dessa forma e, em seguida, agrupar suas várias expressões com o seguinte:
Início do esquema:
começar = lambda * x: x [-1]
Prognóstico Lisp comum:
progn = lambda * x: x [-1]
fonte
Existem soluções melhores sem usar a função lambda. Mas se realmente quisermos usar a função lambda, aqui está uma solução genérica para lidar com várias instruções: map (lambda x: x [1] if (x.sort ()) else x [1], lst)
Você realmente não se importa com o que a declaração retorna.
fonte
Sim, é possível. Experimente o snippet de código abaixo.
fonte
Vou te dar outra solução, Faça seu lambda invocar uma função.
fonte
junky = multiple_statements
.