Programing

반복자가 적어도 하나의 요소를 생성하는지 확인하는 한 줄?

lottogame 2020. 9. 11. 19:25
반응형

반복자가 적어도 하나의 요소를 생성하는지 확인하는 한 줄?


현재 나는 이것을하고있다 :

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

하지만 간단한 if문장 안에 넣을 수있는 표현을 원합니다 . 이 코드를 덜 어색하게 보이게하는 내장 기능이 있습니까?

any()Falseiterable이 비어 있으면 반환 하지만 그렇지 않은 경우 모든 항목을 잠재적으로 반복합니다. 첫 번째 항목 만 확인하면됩니다.


누군가 내가 뭘 하려는지 묻습니다. SQL 쿼리를 실행하고 그 결과를 산출하는 함수를 작성했습니다. 때때로이 함수를 호출 할 때 쿼리가 어떤 것을 반환했는지 알고이를 기반으로 결정을 내리고 싶습니다.


anyTrue이면 첫 번째 요소를 넘어 가지 않습니다. 반복자가 잘못된 것을 산출하는 경우 any(True for _ in iterator).


Python 2.6 이상에서 이름 sentinel이 반복자가 산출 할 수없는 값에 바인딩 된 경우

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

이터레이터가 무엇을 산출 할 수 있을지 모르는 경우 다음을 사용하여 자신의 센티넬 (예 : 모듈 상단)을 만드십시오.

sentinel = object()

그렇지 않으면 센티넬 역할에서 반복자가 산출 할 수없는 (응용 프로그램 고려 사항에 따라) "알고있는"값을 사용할 수 있습니다.


이것은 정말로 깨끗하지는 않지만 무손실 함수로 패키징하는 방법을 보여줍니다.

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은 많은 이터 러블에서 유효한 요소가 될 수 있기 때문에 일반적이지 않습니다.


당신이 사용할 수있는:

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

__length_hint__ estimates the length of list(it) - it's private method, though:

x = iter( (1, 2, 3) )
help(x.__length_hint__)
      1 Help on built-in function __length_hint__:
      2 
      3 __length_hint__(...)
      4     Private method returning an estimate of len(list(it)).

This is an overkill iterator wrapper that generally allows to check whether there's a next item (via conversion to boolean). Of course pretty inefficient.

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)

Output:

False
[]
True
[1, 2, 3]

A little late, but... You could turn the iterator into a list and then work with that list:

# 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

반응형