O código Python a seguir parece ser muito longo quando proveniente de um plano de fundo do Matlab
>>> a = [1, 2, 3, 1, 2, 3]
>>> [index for index,value in enumerate(a) if value > 2]
[2, 5]
Quando em Matlab eu posso escrever:
>> a = [1, 2, 3, 1, 2, 3];
>> find(a>2)
ans =
3 6
Existe um método breve de escrever isso em Python, ou eu continuo com a versão longa?
Obrigado por todas as sugestões e explicações da justificativa para a sintaxe do Python.
Depois de encontrar o seguinte no site numpy, acho que encontrei uma solução que eu gosto:
http://docs.scipy.org/doc/numpy/user/basics.indexing.html#boolean-or-mask-index-arrays
A aplicação das informações desse site ao meu problema acima daria o seguinte:
>>> from numpy import array
>>> a = array([1, 2, 3, 1, 2, 3])
>>> b = a>2
array([False, False, True, False, False, True], dtype=bool)
>>> r = array(range(len(b)))
>>> r(b)
[2, 5]
O seguinte deve funcionar (mas não tenho um intérprete Python disponível para testá-lo):
class my_array(numpy.array):
def find(self, b):
r = array(range(len(b)))
return r(b)
>>> a = my_array([1, 2, 3, 1, 2, 3])
>>> a.find(a>2)
[2, 5]
[idx for idx in range(len(a)) if a[idx] > 2]
? A razão pela qual isso é um pouco complicado de fazer em Python é porque ele não usa índices tanto quanto outras linguagens.Respostas:
No Python, você não usaria índices para isso, mas lida apenas com os valores
[value for value in a if value > 2]
. Geralmente, lidar com índices significa que você não está fazendo algo da melhor maneira.Se você não precisa de uma API semelhante ao Matlab de, você usaria numpy , um pacote para arrays multidimensionais e matemática numérica em Python que é fortemente inspirado em Matlab. Você usaria uma matriz numpy em vez de uma lista.
fonte
filtered_ranges_and_angles = [(range, angle) for range, angle in zip(ranges, angles) if should_be_kept(range)]
Outra maneira:
Em geral, lembre-se de que, embora
find
seja uma função pronta para cozinhar, a compreensão da lista é uma solução geral e, portanto, muito poderosa . Nada impede que você escreva umafind
função no Python e use-a mais tarde como desejar. Ou seja:Observe que estou usando listas aqui para imitar o Matlab. Seria mais Pythonic usar geradores e iteradores.
fonte
[i for i,v in enumerate(a) if v > 2]
antes.index
pori
evalue
comv
no original e conte os caracteres.enumerate
maisrange(len(...))
é mais robusto e mais eficiente.find_indices
função para usoenumerate
Para mim, funciona bem:
fonte
Talvez outra pergunta seja: "o que você fará com esses índices depois de obtê-los?" Se você for usá-los para criar outra lista, no Python, eles serão um passo intermediário desnecessário. Se você deseja todos os valores que correspondem a uma determinada condição, basta usar o filtro interno:
Ou escreva sua própria lista:
Se você deseja removê-los da lista, a maneira Pythonic não é necessariamente removê-la da lista, mas escreva uma compreensão da lista como se estivesse criando uma nova lista e atribuindo-a de volta no local usando o
listvar[:]
lado esquerdo -lado:O Matlab fornece
find
porque seu modelo centralizado em matriz funciona selecionando itens usando seus índices de matriz. Você pode fazer isso em Python, certamente, mas a maneira mais Pythonic é usar iteradores e geradores, como já mencionado por @EliBendersky.fonte
a[:] = ...
- veja a resposta de Alex Martelli a esta pergunta stackoverflow.com/questions/1352885/… .Mesmo que seja uma resposta tardia: acho que essa ainda é uma pergunta muito boa e o IMHO Python (sem bibliotecas ou kits de ferramentas adicionais como numpy) ainda não possui um método conveniente para acessar os índices dos elementos da lista de acordo com um filtro definido manualmente.
Você pode definir manualmente uma função, que fornece essa funcionalidade:
Rendimentos: [0, 4]
Na minha imaginação, o caminho perfeito seria criar uma classe de lista filho e adicionar os índices como método de classe. Dessa maneira, apenas o método de filtro seria necessário:
Eu elaborei um pouco mais sobre esse tópico aqui: http://tinyurl.com/jajrr87
fonte