'for' 루프의 마지막 요소를 감지하는 피토닉 방법은 무엇입니까?
포루프의 마지막 요소를 특수 처리하는 가장 좋은 방법(좀 더 콤팩트하고 "피토닉한" 방법)을 알고 싶습니다.요소 간에만 호출해야 하는 코드가 있으며 마지막 요소에서는 억제됩니다.
현재 사용하고 있는 방법은 다음과 같습니다.
for i, data in enumerate(data_list):
code_that_is_done_for_every_element
if i != len(data_list) - 1:
code_that_is_done_between_elements
더 좋은 방법은 없을까?
주의: 사용법 등의 해킹으로 만들고 싶지 않습니다.reduce
;)
대부분의 경우 첫 번째 반복을 마지막 반복이 아닌 특별한 경우로 만드는 것이 더 쉽고 더 저렴합니다.
first = True
for data in data_list:
if first:
first = False
else:
between_items()
item()
수 있는 모든 할 수 . 이 방법이 입니다.len()
:
file = open('/path/to/file')
for line in file:
process_line(line)
# No way of telling if this is the last line!
그것 말고는, 무엇을 하려고 하는가에 따라 다르기 때문에, 일반적으로 뛰어난 해결책은 없다고 생각합니다.들어 '아까', '아까', '아까', '아까', '아까', '아까'를 사용하는 것이 좋습니다.str.join()
than using using a a a a a using를 사용하는 것보다for
★★★★★★★★★★★★★★★★★★★★★★★★★★」
같은 원리로 보다 콤팩트하게 사용:
for i, line in enumerate(data_list):
if i > 0:
between_items()
item()
어디서 많이 본 것 같지 않아?:)
@ @ofko가 없는 값이 있는지 가 있는 @ofko를 하십시오.len()
마지막입니다.앞을 내다볼 필요가 있습니다.
def lookahead(iterable):
"""Pass through all values from the given iterable, augmented by the
information if there are more values to come after the current one
(True), or if it is the last value (False).
"""
# Get an iterator and pull the first value.
it = iter(iterable)
last = next(it)
# Run the iterator to exhaustion (starting from the second value).
for val in it:
# Report the *previous* value (more to come).
yield last, True
last = val
# Report the last value.
yield last, False
그 후 다음과 같이 사용할 수 있습니다.
>>> for i, has_more in lookahead(range(3)):
... print(i, has_more)
0 True
1 True
2 False
그 질문은 꽤 오래되었지만 구글을 통해 찾아왔고 꽤 간단한 방법을 찾았습니다: 리스트 슬라이스.모든 목록 항목 사이에 &을 삽입한다고 가정해 보겠습니다.
s = ""
l = [1, 2, 3]
for i in l[:-1]:
s = s + str(i) + ' & '
s = s + str(l[-1])
이것은 '1 & 2 & 3'을 반환합니다.
항목이 고유할 경우:
for x in list:
#code
if x == list[-1]:
#code
기타 옵션:
pos = -1
for x in list:
pos += 1
#code
if pos == len(list) - 1:
#code
for x in list:
#code
#code - e.g. print x
if len(list) > 0:
for x in list[:-1]
#code
for x in list[-1]:
#code
'code between'은 헤드테일 패턴의 예입니다.
항목이 있고, 그 뒤에 (항목 간) 쌍이 계속됩니다.또한 이를 일련의 (항목, 항목 간) 쌍으로 보고 그 다음에 항목을 볼 수도 있습니다.일반적으로 첫 번째 요소를 특수 요소로 간주하고 다른 요소를 모두 "표준" 사례로 간주하는 것이 더 쉽습니다.
또한 코드 반복을 방지하려면 반복하지 않을 코드를 포함하는 함수 또는 다른 개체를 제공해야 합니다.if 문을 루프에 삽입하는 것은 한 번을 제외하고 항상 거짓입니다.
def item_processing( item ):
# *the common processing*
head_tail_iter = iter( someSequence )
head = next(head_tail_iter)
item_processing( head )
for item in head_tail_iter:
# *the between processing*
item_processing( item )
이 방법은 증명하기가 약간 더 쉬우며, 추가 데이터 구조(목록 복사본 등)를 생성하지 않으며, 한 번을 제외하고는 항상 잘못된 if 조건의 많은 낭비가 필요하지 않기 때문에 더욱 신뢰할 수 있습니다.
의 를 단순히 data_list
을 사용하다
L[-1]
하지만, 당신은 그 이상을 하고 있는 것처럼 보입니다.당신 방식에는 별로 문제될 게 없어요.템플릿 태그의 Django 코드도 잠깐 봤는데 기본적으로는 그렇게 되어 있어요.
마지막 요소는 다음 코드로 판별할 수 있습니다.
for i,element in enumerate(list):
if (i==len(list)-1):
print("last element is" + element)
이것은 Ants Aasma의 접근법과 비슷하지만 반복 도구 모듈을 사용하지 않습니다.또한 반복기 스트림의 단일 요소를 미리 파악하는 지연 반복기입니다.
def last_iter(it):
# Ensure it's an iterator and get the first field
it = iter(it)
prev = next(it)
for item in it:
# Lag by one item so I know I'm not at the end
yield 0, prev
prev = item
# Last item
yield 1, prev
def test(data):
result = list(last_iter(data))
if not result:
return
if len(result) > 1:
assert set(x[0] for x in result[:-1]) == set([0]), result
assert result[-1][0] == 1
test([])
test([1])
test([1, 2])
test(range(5))
test(xrange(4))
for is_last, item in last_iter("Hi!"):
print is_last, item
하려면 , 「 」를 사용합니다.for-else
cities = [
'Jakarta',
'Surabaya',
'Semarang'
]
for city in cities[:-1]:
print(city)
else:
print(' '.join(cities[-1].upper()))
출력:
Jakarta
Surabaya
S E M A R A N G
는 ''만 사용한다는 입니다.for-else
" "까지 "n-1
그 후 "" 뒤에 .for
소진되면 마지막 할 수 있습니다. 이치노[-1]
.
입력 데이터 위에 슬라이딩 창을 사용하여 다음 값을 엿보고 Sentinel을 사용하여 마지막 값을 탐지할 수 있습니다.이것은 반복할 수 있기 때문에, 사전에 길이를 알 필요는 없습니다.쌍별 구현은 반복 도구의 레시피에서 이루어집니다.
from itertools import tee, izip, chain
def pairwise(seq):
a,b = tee(seq)
next(b, None)
return izip(a,b)
def annotated_last(seq):
"""Returns an iterable of pairs of input item and a boolean that show if
the current item is the last item in the sequence."""
MISSING = object()
for current_item, next_item in pairwise(chain(seq, [MISSING])):
yield current_item, next_item is MISSING:
for item, is_last_item in annotated_last(data_list):
if is_last_item:
# current item is the last item
마지막 요소를 제외한 모든 요소를 반복하고 마지막 요소를 루프 밖에서 처리할 가능성은 없습니까?결국, 루프는 여러분이 루프오버하는 모든 요소와 유사한 작업을 수행하기 위해 생성됩니다. 만약 한 요소가 특별한 것을 필요로 한다면, 루프는 루프 안에 있지 않아야 합니다.
(「does-the-the-last-in-a-loop-timeout-a-timeout」도 참조).
편집: 질문은 "사이"에 대한 것이므로 첫 번째 요소는 이전 요소가 없다는 점에서 특수 요소이거나 마지막 요소는 후속 요소가 없다는 점에서 특수 요소입니다.
@, @ethan-t는 @ethan-t입니다.while True
제 관점에서 보면 위험합니다.
data_list = [1, 2, 3, 2, 1] # sample data
L = list(data_list) # destroy L instead of data_list
while L:
e = L.pop(0)
if L:
print(f'process element {e}')
else:
print(f'process last element {e}')
del L
서서,,data_list
마지막 요소가 목록의 첫 번째 요소와 값에 의해 동일하도록 하는 것입니다.은 L로 할 수 .data_list
, 이 loop.loop.loop 뒤에 되지 않습니다. while True
가공 전에 리스트가 비어 있지 않은지 확인하거나 체크가 필요 없는 경우(aouch!)도 사용할 수 있습니다.
data_list = [1, 2, 3, 2, 1]
if data_list:
while True:
e = data_list.pop(0)
if data_list:
print(f'process element {e}')
else:
print(f'process last element {e}')
break
else:
print('list is empty')
좋은 점은 빠르다는 것이다.것은 수 있다.data_list
비게 됩니다).
가장 직관적인 솔루션:
data_list = [1, 2, 3, 2, 1] # sample data
for i, e in enumerate(data_list):
if i != len(data_list) - 1:
print(f'process element {e}')
else:
print(f'process last element {e}')
그래, 이미 제안했구나!
루프가 100,000개 있고 "if" 문장이 100,000개 저장되지 않는 한 방법에는 아무런 문제가 없습니다.이 경우는, 다음의 방법으로 실행할 수 있습니다.
iterable = [1,2,3] # Your date
iterator = iter(iterable) # get the data iterator
try : # wrap all in a try / except
while 1 :
item = iterator.next()
print item # put the "for loop" code here
except StopIteration, e : # make the process on the last element here
print item
출력:
1
2
3
3
하지만 정말로, 당신 경우엔 과잉 살상인 것 같아요.
어느 경우든 슬라이스를 하면 운이 더 좋을 것입니다.
for item in iterable[:-1] :
print item
print "last :", iterable[-1]
#outputs
1
2
last : 3
또는 단순히:
for item in iterable :
print item
print iterable[-1]
#outputs
1
2
3
last : 3
은, 「KISS」, 「KISS」, 「KISS」, 「KISS」, 「」가 없는 반복 가능한 합니다.__len__
:
item = ''
for item in iterable :
print item
print item
출력:
1
2
3
3
내가 그렇게 할 것 같다면, 내겐 간단해 보인다.
슬라이스를 사용하여is
「 」 「 」 소인 :
for data in data_list:
<code_that_is_done_for_every_element>
if not data is data_list[-1]:
<code_that_is_done_between_elements>
경고 비우기:이것은, 리스트내의 모든 요소가 실제로 다른 경우(메모리내의 위치가 다른 경우)에만 유효합니다.후드에서 Python은 동일한 요소를 감지하여 동일한 개체를 재사용할 수 있습니다.예를 들어 동일한 값과 공통 정수의 문자열입니다.
구글은 나에게 이 오래된 질문을 했고 나는 내가 이 문제에 다른 접근법을 추가할 수 있다고 생각한다.
대부분의 답변은 요구대로 루프 제어를 위한 적절한 처리를 다루고 있지만 data_list가 파괴 가능한 경우 목록에서 항목을 팝업하여 빈 목록을 표시할 것을 권장합니다.
while True:
element = element_list.pop(0)
do_this_for_all_elements()
if not element:
do_this_only_for_last_element()
break
do_this_for_all_elements_but_last()
마지막 요소로 아무것도 할 필요가 없는 경우 len(len_list)을 사용할 수도 있습니다.저는 이 솔루션이 다음 솔루션보다 더 우아하다고 생각합니다.
하다의 가 사용되었습니다.enumerate()
, 「」, 「」만을 하고 있습니다i
인덱스를 클릭하여 목록의 마지막 항목인지 확인합니다. 더 없는).enumerate()
의 인덱스를
for data in data_list:
code_that_is_done_for_every_element
if data != data_list[-1]:
code_that_is_done_between_elements
if data != data_list[-1]
는 반복의 현재 항목이 목록의 마지막 항목이 아닌지 확인합니다.
거의 11년이 지난 지금이라도 이것이 도움이 되길 바랍니다.
목록을 살펴보신다면, 저도 마찬가지입니다.
for j in range(0, len(Array)):
if len(Array) - j > 1:
notLast()
목록 끝에 있는 특수한 경우를 처리하는 가장 단순하고 피조적인 방법은 다음과 같습니다.
for data in data_list[:-1]:
handle_element(data)
handle_special_element(data_list[-1])
물론 이것은 첫 번째 요소를 특별한 방법으로 처리하는 데에도 사용될 수 있습니다.
카운트업 대신 카운트다운을 할 수도 있습니다.
nrToProcess = len(list)
for s in list:
s.doStuff()
nrToProcess -= 1
if nrToProcess==0: # this is the last one
s.doSpecialStuff()
마지막 항목의 특별 취급을 루프 후까지 지연시킵니다.
>>> for i in (1, 2, 3):
... pass
...
>>> i
3
여러 가지 방법이 있을 수 있습니다.슬라이스가 가장 빠릅니다..index() 메서드를 사용하는 하나 더 추가:
>>> l1 = [1,5,2,3,5,1,7,43]
>>> [i for i in l1 if l1.index(i)+1==len(l1)]
[43]
포장을 풀어서 다음과 같이 보다 우아하고 견고한 방법을 제공합니다.
def mark_last(iterable):
try:
*init, last = iterable
except ValueError: # if iterable is empty
return
for e in init:
yield e, True
yield last, False
테스트:
for a, b in mark_last([1, 2, 3]):
print(a, b)
결과는 다음과 같습니다.
True 1 »
True2 »
False 3 짓 3
「」를 있는 .List
를 사용합니다.enumerate
이치
for index, element in enumerate(ListObj):
# print(index, ListObj[index], len(ListObj) )
if (index != len(ListObj)-1 ):
# Do things to the element which is not the last one
else:
# Do things to the element which is the last one
목록을 파괴하는 것에 만족한다면, 다음과 같은 것이 있습니다.pop(0)은 반복할 때마다 목록을 이동하기 때문에 프로세스를 O(n^2)에서 O(n)로 고속화하기 위해 목록을 반전합니다.니콜라스 피피톤의 코멘트
data_list.reverse()
while data_list:
value = data_list.pop()
code_that_is_done_for_every_element(value)
if data_list:
code_that_is_done_between_elements(value)
else:
code_that_is_done_for_last_element(value)
이 기능은 빈 목록 및 고유하지 않은 항목 목록과 함께 사용할 수 있습니다.리스트는 일시적인 경우가 많기 때문에, 이것은 꽤 잘 동작합니다.목록을 파기하는 댓가를 치뤄야 합니다.
입력을 반복기로 가정하면, 다음은 반복 도구에서 tee와 izip을 사용하는 방법입니다.
from itertools import tee, izip
items, between = tee(input_iterator, 2) # Input must be an iterator.
first = items.next()
do_to_every_item(first) # All "do to every" operations done to first item go here.
for i, b in izip(items, between):
do_between_items(b) # All "between" operations go here.
do_to_every_item(i) # All "do to every" operations go here.
데모:
>>> def do_every(x): print "E", x
...
>>> def do_between(x): print "B", x
...
>>> test_input = iter(range(5))
>>>
>>> from itertools import tee, izip
>>>
>>> items, between = tee(test_input, 2)
>>> first = items.next()
>>> do_every(first)
E 0
>>> for i,b in izip(items, between):
... do_between(b)
... do_every(i)
...
B 0
E 1
B 1
E 2
B 2
E 3
B 3
E 4
>>>
가장 간단한 해결책은 다음과 같습니다.
for item in data_list:
try:
print(new)
except NameError: pass
new = item
print('The last item: ' + str(new))
그래서 우리는 항상 하나의 반복 처리를 지연시킴으로써 하나의 항목을 예측합니다.첫 번째 반복 중에 무언가를 하는 것을 건너뛰는 것은 단순히 오류를 발견하는 것이다.
물론 좀 더 생각해보셔야 합니다.NameError
네가 원할 때 키울 수 있어
또, 「명령」도 보관해 주세요.
try:
new
except NameError: pass
else:
# continue here if no error was raised
이것은 new라는 이름이 사전에 정의되어 있지 않은 것에 의존합니다.만약 당신이 편집증적이라면, 당신은 확실히 할 수 있다.new
존재하지 않는 방법:
try:
del new
except NameError:
pass
물론 if 문을 사용할 수도 있습니다.if notfirst: print(new) else: notfirst = True
하지만 오버헤드가 더 큰 것으로 알고 있습니다.
Using `timeit` yields:
...: try: new = 'test'
...: except NameError: pass
...:
100000000 loops, best of 3: 16.2 ns per loop
그래서 나는 오버헤드를 선택할 수 없을 것으로 예상한다.
항목을 한 번 세고 남은 항목 수를 파악합니다.
remaining = len(data_list)
for data in data_list:
code_that_is_done_for_every_element
remaining -= 1
if remaining:
code_that_is_done_between_elements
이렇게 하면 목록의 길이를 한 번만 평가할 수 있습니다.이 페이지의 솔루션 중 상당수는 이 길이를 미리 사용할 수 없다고 가정하고 있는 것 같습니다만, 그것은 질문의 일부가 아닙니다.길이가 있으면 쓰세요.
생각할 수 있는 간단한 솔루션은 다음과 같습니다.
for i in MyList:
# Check if 'i' is the last element in the list
if i == MyList[-1]:
# Do something different for the last
else:
# Do something for all other elements
마찬가지로 간단한 두 번째 솔루션은 카운터를 사용하여 달성할 수 있습니다.
# Count the no. of elements in the list
ListLength = len(MyList)
# Initialize a counter
count = 0
for i in MyList:
# increment counter
count += 1
# Check if 'i' is the last element in the list
# by using the counter
if count == ListLength:
# Do something different for the last
else:
# Do something for all other elements
data_list의 마지막 데이터와 동일하지 않은지 확인만 하면 됩니다.(data_list[-1]
를 참조해 주세요.
for data in data_list:
code_that_is_done_for_every_element
if data != data_list[- 1]:
code_that_is_done_between_elements
따라서, 이것은 확실히 "짧은" 버전이 아니며, "가장 짧은"과 "피토닉"이 실제로 호환된다면 다른 말로 넘어갈 수도 있습니다.
이 이 자주 로직을 된 메타 를 직접 10-라이너 .for
또 다른 뿐만 아니라 가능한 한다는 것입니다. 여기서 또 다른 장점은 시퀀스뿐만 아니라 임의의 반복이 가능한 상태에서 작동한다는 것입니다.
_sentinel = object()
def iter_check_last(iterable):
iterable = iter(iterable)
current_element = next(iterable, _sentinel)
while current_element is not _sentinel:
next_element = next(iterable, _sentinel)
yield (next_element is _sentinel, current_element)
current_element = next_element
In [107]: for is_last, el in iter_check_last(range(3)):
...: print(is_last, el)
...:
...:
False 0
False 1
True 2
이것은 오래된 질문이고 이미 많은 좋은 반응들이 있지만, 저는 이것이 꽤 피토닉한 것이라고 느꼈습니다.
def rev_enumerate(lst):
"""
Similar to enumerate(), but counts DOWN to the last element being the
zeroth, rather than counting UP from the first element being the zeroth.
Since the length has to be determined up-front, this is not suitable for
open-ended iterators.
Parameters
----------
lst : Iterable
An iterable with a length (list, tuple, dict, set).
Yields
------
tuple
A tuple with the reverse cardinal number of the element, followed by
the element of the iterable.
"""
length = len(lst) - 1
for i, element in enumerate(lst):
yield length - i, element
다음과 같이 사용:
for num_remaining, item in rev_enumerate(['a', 'b', 'c']):
if not num_remaining:
print(f'This is the last item in the list: {item}')
또는 그 반대의 경우도 있습니다.
for num_remaining, item in rev_enumerate(['a', 'b', 'c']):
if num_remaining:
print(f'This is NOT the last item in the list: {item}')
아니면 얼마나 남았는지 알기 위해서...
for num_remaining, item in rev_enumerate(['a', 'b', 'c']):
print(f'After {item}, there are {num_remaining} items.')
합니다.enumerate
가장 피조어적인 것으로 만들죠
경고, 다음과는 다릅니다.enumerate()
,rev_enumerate()
에서는, 입력 실장 「실행」이 합니다.__len__
아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아.
언급URL : https://stackoverflow.com/questions/1630320/what-is-the-pythonic-way-to-detect-the-last-element-in-a-for-loop
'programing' 카테고리의 다른 글
속성을 프로그래밍 방식으로 설정하려면 어떻게 해야 합니까? (0) | 2022.09.27 |
---|---|
MySQL 오류 1153 - 'max_allowed_packet' 바이트보다 큰 패킷을 받았습니다. (0) | 2022.09.27 |
MariaDB 아카이브 엔진 설치 (0) | 2022.09.27 |
Moment.js를 최신 개체로 변환 (0) | 2022.09.27 |
mysql 워크벤치를 통해 mysql 데이터베이스로 데이터를 Import하려면 어떻게 해야 합니까? (0) | 2022.09.27 |