[python] range (len (a))가 필요합니까?

SO에 대한 파이썬 질문에서 이러한 유형의 표현을 자주 찾습니다. iterable의 모든 항목에 액세스하기 위해

for i in range(len(a)):
    print(a[i])

어색한 글쓰기 방법입니다.

for e in a:
    print(e)

또는 iterable의 요소에 할당하는 경우 :

for i in range(len(a)):
    a[i] = a[i] * 2

다음과 같아야합니다.

for i, e in enumerate(a):
     a[i] = e * 2
# Or if it isn't too expensive to create a new iterable
a = [e * 2 for e in a]

또는 인덱스 필터링 :

for i in range(len(a)):
    if i % 2 == 1: continue
    print(a[i])

다음과 같이 표현할 수 있습니다.

for e in a [::2]:
    print(e)

또는 목록의 내용이 아닌 길이 만 필요한 경우 :

for _ in range(len(a)):
    doSomethingUnrelatedToA()

다음 중 하나 일 수 있습니다.

for _ in a:
    doSomethingUnrelatedToA()

우리가 파이썬에서 enumerate, 슬라이스, filter, sorted, 파이썬 등 …으로 for구조가 반복 가능 객체를 반복하기위한 것입니다 및뿐만 아니라 정수의 범위, 당신이 필요가 실제 사용 사례는 in range(len(a))?



답변

시퀀스의 인덱스로 작업해야하는 경우 예-사용합니다 … 예를 들어 numpy.argsort에 해당하는 경우 … :

>>> a = [6, 3, 1, 2, 5, 4]
>>> sorted(range(len(a)), key=a.__getitem__)
[2, 3, 1, 5, 4, 0]


답변

목록의 두 요소에 동시에 액세스해야하는 경우 어떻게해야합니까?

for i in range(len(a[0:-1])):
    something_new[i] = a[i] * a[i+1]

이것을 사용할 수는 있지만 명확하지 않을 수 있습니다.

for i, _ in enumerate(a[0:-1]):
     something_new[i] = a[i] * a[i+1]

개인적으로 나도 100 % 만족하지 않습니다!


답변

짧은 대답 : 수학적으로 말하면 아니오, 실제적인 측면에서 예, 예를 들어 의도적 프로그래밍의 경우.

기술적으로 대답은 다른 구조를 사용하여 표현할 수 있기 때문에 “아니요, 필요하지 않습니다” 입니다. 그러나 실제로는 for i in range(len(a)(또는 for _ in range(len(a))인덱스가 필요하지 않은 경우) 시퀀스의 항목을 아무것도 사용할 필요없이 시퀀스에 항목이있는만큼 반복하고 싶다는 것을 명시 적으로 사용합니다.

그래서 : “필요가 있습니까?” ? — 예, 가독성을 위해 코드의 의미 / 의도를 표현하는 데 필요 합니다.

참조 : https://en.wikipedia.org/wiki/Intentional_programming

그리고 분명히 반복과 관련된 컬렉션이 전혀없는 경우에 for ... in range(len(N))의지하지 않는 유일한 옵션입니다.i = 0; while i < N; i += 1 ...


답변

의견뿐만 아니라 개인적인 경험으로 가고, 나는 더 없다, 더 말할 필요 에 대한이 range(len(a)). 할 수있는 모든 range(len(a))작업은 다른 방식 (일반적으로 훨씬 더 효율적)으로 수행 할 수 있습니다.

게시물에 많은 예를 주셨으므로 여기서 반복하지 않겠습니다. 대신 ” a항목이 아닌의 길이 만 원하면 어떨까요?” 라고 말하는 사람들을 위해 예를 들어 보겠습니다 . 이것은 사용을 고려할 수있는 유일한 경우 중 하나입니다 range(len(a)). 그러나 이것도 다음과 같이 할 수 있습니다.

>>> a = [1, 2, 3, 4]
>>> for _ in a:
...     print True
...
True
True
True
True
>>>

Clements 답변 (Allik에 의해 표시됨)을 다시 작업하여 range(len(a))다음 을 제거 할 수도 있습니다 .

>>> a = [6, 3, 1, 2, 5, 4]
>>> sorted(range(len(a)), key=a.__getitem__)
[2, 3, 1, 5, 4, 0]
>>> # Note however that, in this case, range(len(a)) is more efficient.
>>> [x for x, _ in sorted(enumerate(a), key=lambda i: i[1])]
[2, 3, 1, 5, 4, 0]
>>>

따라서 결론적으로 range(len(a))필요 하지 않습니다 . 유일한 장점은 가독성입니다 (의도는 분명합니다). 그러나 그것은 단지 선호도와 코드 스타일 일뿐입니다.


답변

때때로하기 matplotlib 필요 range(len(y))하지만, 예를 들어, y=array([1,2,5,6]), plot(y), 잘 작동 scatter(y)하지 않습니다. 하나는 써야한다 scatter(range(len(y)),y). (개인적으로, 나는 이것이 버그라고 생각 scatter, plot그 친구 scatterstem가능한 한 같은 호출 시퀀스를 사용해야합니다.)


답변

어떤 종류의 조작을 위해 인덱스를 사용해야 할 때 현재 요소가 충분하지 않을 때 있으면 좋습니다. 예를 들어 배열에 저장된 이진 트리를 생각해보십시오. 각 노드의 직계 자식을 포함하는 튜플 목록을 반환하도록 요청하는 메서드가있는 경우 인덱스가 필요합니다.

#0 -> 1,2 : 1 -> 3,4 : 2 -> 5,6 : 3 -> 7,8 ...
nodes = [0,1,2,3,4,5,6,7,8,9,10]
children = []
for i in range(len(nodes)):
  leftNode = None
  rightNode = None
  if i*2 + 1 < len(nodes):
    leftNode = nodes[i*2 + 1]
  if i*2 + 2 < len(nodes):
    rightNode = nodes[i*2 + 2]
  children.append((leftNode,rightNode))
return children

물론 작업중인 요소가 객체 인 경우 get children 메서드를 호출 할 수 있습니다. 그러나 예, 일종의 조작을 수행하는 경우에만 인덱스가 필요합니다.


답변

귀하의 예제 중 어느 것도 다루지 않는다고 생각하는 사용 사례가 있습니다.

boxes = [b1, b2, b3]
items = [i1, i2, i3, i4, i5]
for j in range(len(boxes)):
    boxes[j].putitemin(items[j])

나는 더 우아한 접근 방식을 배우는 것이 너무 행복하지만 파이썬에 비교적 익숙하지 않습니다.