[python] python list comprehension을 사용하여 조건에 따라 요소의 인덱스 찾기

다음 Python 코드는 Matlab 배경에서 올 때 매우 긴 것으로 보입니다.

>>> a = [1, 2, 3, 1, 2, 3]
>>> [index for index,value in enumerate(a) if value > 2]
[2, 5]

Matlab에서 다음과 같이 작성할 수 있습니다.

>> a = [1, 2, 3, 1, 2, 3];
>> find(a>2)
ans =
     3     6

이것을 파이썬으로 작성하는 짧은 방법이 있습니까, 아니면 긴 버전을 고수합니까?


파이썬 구문의 근거에 대한 모든 제안과 설명에 감사드립니다.

numpy 웹 사이트에서 다음을 찾은 후 내가 좋아하는 솔루션을 찾은 것 같습니다.

http://docs.scipy.org/doc/numpy/user/basics.indexing.html#boolean-or-mask-index-arrays

해당 웹 사이트의 정보를 위의 문제에 적용하면 다음이 제공됩니다.

>>> 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]

그러면 다음이 작동합니다 (그러나 테스트 할 Python 인터프리터가 없습니다).

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]



답변

  • Python에서는이를 위해 인덱스를 전혀 사용하지 않고 값만 처리합니다 [value for value in a if value > 2]. 일반적으로 인덱스를 다루는 것은 최선의 방법을 사용하지 않는다는 것을 의미합니다.

  • Matlab과 유사한 API 필요한 경우 Matlab에서 크게 영감을받은 Python의 다차원 배열 및 수치 수학 패키지 인 numpy를 사용 합니다. 목록 대신 numpy 배열을 사용합니다.

    >>> import numpy
    >>> a = numpy.array([1, 2, 3, 1, 2, 3])
    >>> a
    array([1, 2, 3, 1, 2, 3])
    >>> numpy.where(a > 2)
    (array([2, 5]),)
    >>> a > 2
    array([False, False,  True, False, False,  True], dtype=bool)
    >>> a[numpy.where(a > 2)]
    array([3, 3])
    >>> a[a > 2]
    array([3, 3])

답변

또 다른 방법:

>>> [i for i in range(len(a)) if a[i] > 2]
[2, 5]

일반적으로, 그 기억 하면서이 find준비 조리 기능입니다, 지능형리스트는 일반적으로, 따라서 매우 강력한 솔루션입니다 . find파이썬 으로 함수 를 작성하고 나중에 원하는대로 사용 하는 것을 방해하는 것은 없습니다 . 즉 :

>>> def find_indices(lst, condition):
...   return [i for i, elem in enumerate(lst) if condition(elem)]
...
>>> find_indices(a, lambda e: e > 2)
[2, 5]

여기서는 Matlab을 모방하기 위해 목록을 사용하고 있습니다. 생성기와 반복기를 사용하는 것이 더 파이썬적일 것입니다.


답변

나에게는 잘 작동합니다.

>>> import numpy as np
>>> a = np.array([1, 2, 3, 1, 2, 3])
>>> np.where(a > 2)[0]
[2 5]


답변

또 다른 질문은 “그 인덱스를 받으면 어떻게 하시겠습니까?”일 수 있습니다. 그것들을 사용하여 다른 목록을 만들려면 Python에서 불필요한 중간 단계입니다. 주어진 조건과 일치하는 모든 값을 원한다면 내장 필터를 사용하십시오.

matchingVals = filter(lambda x : x>2, a)

또는 자신의 목록 이해력을 작성하십시오.

matchingVals = [x for x in a if x > 2]

목록에서 제거하려는 경우 Python 방식은 반드시 목록에서 제거하는 것이 아니라 새 목록을 생성하는 것처럼 목록 이해력을 작성 listvar[:]하고 왼쪽에 있는를 사용하여 제자리에 다시 할당하는 것 입니다. -측면:

a[:] = [x for x in a if x <= 2]

Matlab find은 배열 중심 모델이 배열 인덱스를 사용하여 항목을 선택하여 작동하기 때문에 제공합니다. 당신은 할 수 확실히 파이썬에서이 작업을 수행하지만, 더 파이썬 방법은 이미 @EliBendersky 언급 반복자 발전기를 사용하고 있습니다.


답변

늦은 답변이라 할지라도 : 이것은 여전히 ​​매우 좋은 질문이라고 생각하며 IMHO Python (numpy와 같은 추가 라이브러리 또는 툴킷이 없음)에는 수동으로 정의 된 필터에 따라 목록 요소의 인덱스에 액세스하는 편리한 방법이 여전히 부족합니다.

해당 기능을 제공하는 함수를 수동으로 정의 할 수 있습니다.

def indices(list, filtr=lambda x: bool(x)):
    return [i for i,x in enumerate(list) if filtr(x)]

print(indices([1,0,3,5,1], lambda x: x==1))

수율 : [0, 4]

내 상상에서 완벽한 방법은 목록의 자식 클래스를 만들고 인덱스 함수를 클래스 메서드로 추가하는 것입니다. 이런 식으로 필터 메서드 만 필요합니다.

class MyList(list):
    def __init__(self, *args):
        list.__init__(self, *args)
    def indices(self, filtr=lambda x: bool(x)):
        return [i for i,x in enumerate(self) if filtr(x)]

my_list = MyList([1,0,3,5,1])
my_list.indices(lambda x: x==1)

이 주제에 대해 좀 더 자세히 설명했습니다.
http://tinyurl.com/jajrr87


답변