bestsource

반복기가 적어도 하나의 요소를 산출하는지 확인하기 위한 원라이너?

bestsource 2023. 7. 28. 22:28
반응형

반복기가 적어도 하나의 요소를 산출하는지 확인하기 위한 원라이너?

현재 이 작업을 수행하고 있습니다.

try:
    something = next(iterator)
    # ...
except StopIteration:
    # ...

하지만 저는 심플한 안에 넣을 수 있는 표현을 원합니다.if진술.이 코드를 덜 서툴게 보이게 하는 내장된 것이 있습니까?저는 첫 번째 항목만 확인하면 됩니다.

if any(True for _ in iterator):
    print('iterator had at least one element')
if all(False for _ in iterator):
    print('iterator was empty')

하나 이상의 요소가 있는 경우 반복 가능한 항목의 첫 번째 요소가 사용됩니다.

Sentinel 값을 기본값으로 전달next():

sentinel = object()

if next(iterator, sentinel) is sentinel:
    print('iterator was empty')

또한 반복자가 생성할 수 없는 "알고 있는" 값(응용프로그램 고려사항에 따라)을 센티널 값으로 사용할 수도 있습니다.

이것은 사실 더 깨끗하지는 않지만, 손실 없이 기능으로 패키지화하는 방법을 보여줍니다.

def has_elements(iter):
  from itertools import tee
  iter, any_check = tee(iter)
  try:
    any_check.next()
    return True, iter
  except StopIteration:
    return False, iter

has_el, iter = has_elements(iter)
if has_el:
  # not empty

이것은 실제로는 부정적인 것이 아니며, 특정한 경우에는 다음 기본값과 같은 더 나은(그러나 덜 일반적인) 해결책이 있을 수 있습니다.

first = next(iter, None)
if first:
  # Do something

None은 많은 반복 가능한 요소일 수 있으므로 일반적이지 않습니다.

그렇게 하는 가장 좋은 방법은peekable부터more_itertools.

from more_itertools import peekable
iterator = peekable(iterator)
if iterator:
    # Iterator is non-empty.
else:
    # Iterator is empty.

만약 당신이 오래된 반복기에 대한 참조를 유지한다면, 그 반복기는 발전할 것입니다.당신은 그때부터 새로운 훔쳐보기 가능한 반복기를 사용해야 합니다.peekable이전 반복기를 수정하는 유일한 코드 비트가 될 것으로 예상됩니다.

사용할 수 있는 항목:

if zip([None], iterator):
    # ...
else:
    # ...

하지만 코드 리더에게는 설명할 수 없는 일입니다.

다음은 어떻습니까?

In [1]: i=iter([])

In [2]: bool(next(i,False))
Out[2]: False

In [3]: i=iter([1])

In [4]: bool(next(i,False))
Out[4]: True

일반적으로 다음 항목이 있는지 확인할 수 있는 오버킬 반복기 래퍼입니다.물론 꽤 비효율적입니다.

class LookaheadIterator ():

    def __init__(self, iterator):
        self.__iterator = iterator
        try:
            self.__next      = next (iterator)
            self.__have_next = True
        except StopIteration:
            self.__have_next = False

    def __iter__(self):
        return self

    def next (self):
        if self.__have_next:
            result = self.__next
            try:
                self.__next      = next (self.__iterator)
                self.__have_next = True
            except StopIteration:
                self.__have_next = False

            return result

        else:
            raise StopIteration

    def __nonzero__(self):
        return self.__have_next

x = LookaheadIterator (iter ([]))
print bool (x)
print list (x)

x = LookaheadIterator (iter ([1, 2, 3]))
print bool (x)
print list (x)

출력:

False
[]
True
[1, 2, 3]

조금 늦었지만, 하지만...반복기를 목록으로 전환한 다음 해당 목록으로 작업할 수 있습니다.

# Create a list of objects but runs out the iterator.
l = [_ for _ in iterator]

# If the list is not empty then the iterator had elements; else it was empty.
if l :
    pass # Use the elements of the list (i.e. from the iterator)
else :
    pass # Iterator was empty, thus list is empty.

언급URL : https://stackoverflow.com/questions/3114252/one-liner-to-check-whether-an-iterator-yields-at-least-one-element

반응형