Острота, чтобы проверить, приводит ли итератор по крайней мере к одному элементу?

Я придерживаюсь более или менее точно такой же проблемы, и я обнаружил открытый дефект по этому вопросу, который имеет смысл ...

https://code.google.com / p / android / issues / detail? id = 174566

Мое обходное решение - пусть и не самое лучшее решение - состоит в том, чтобы никогда не менять ревизию базы данных и не отслеживать ее самостоятельно, поэтому никогда не вызывайте onUpgrade() , и вручную обновлять приложение при обновлении.

Альтернативно, если у вас есть небольшая БД, которая доступна только для чтения, вы можете инициировать копирование db в активах на каждом onCreate() в классе DBHelper , но это может привести к нежелательным проблемам, если файловая система заполнена, поэтому делайте это только при поиске лучшего решения.

@Override
public void onCreate(SQLiteDatabase db) {
    // Workaround for Issue 174566
    myContext.deleteDatabase(DB_NAME);
    try {
        copyDataBase();
    }
    catch(IOException e) {
        System.out.println("IOException " + e.getLocalizedMessage());
    }
}

Мое приложение теперь обновляется, как и должно быть, с моим обходным решением и, судя, потому что этот дефект первоначально был поднят, он вообще никогда не может быть исправлен ...

Извините, что это не полное решение проблемы, но это, по крайней мере, путь вперед.

91
задан Bastien Léonard 24 June 2010 в 23:29
поделиться

7 ответов

any не выйдет за пределы первого элемента, если он равен True. В случае, если итератор выдает что-то ложное, можно написать any(True for _ in iterator).

124
ответ дан 24 November 2019 в 06:46
поделиться

Лучший способ сделать, который является с peekable от more_itertools.

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

Просто остерегаются, если Вы сохранили судей к старому итератору, тот итератор будет усовершенствован. Необходимо использовать новый peekable итератор с тех пор. Действительно, тем не менее, peekable ожидает быть единственным битом кода, изменяющего, что старый итератор, таким образом, Вы не должны сохранять судей к старому итератору, лежащему вокруг так или иначе.

1
ответ дан 24 November 2019 в 06:46
поделиться

Это не совсем чище, но показывает способ упаковать его в функцию без потерь:

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 может быть допустимым элементом во многих итерациях.

19
ответ дан 24 November 2019 в 06:46
поделиться

вы можете использовать:

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

но это немного непонятно для считывателя кодов

6
ответ дан 24 November 2019 в 06:46
поделиться

__ length_hint __ оценивает длину list (it) - хотя это частный метод:

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)).
-1
ответ дан 24 November 2019 в 06:46
поделиться

Это избыточная оболочка итератора, которая обычно позволяет проверять, есть ли следующий элемент (посредством преобразования в логическое значение). Конечно довольно неэффективно.

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]
-1
ответ дан 24 November 2019 в 06:46
поделиться

В Python 2.6+, если имя sentinel привязано к значению, которое итератор не может выдать,

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

Если вы не знаете, что это за итератор может дать результат, создайте свой собственный дозорный (например, в верхней части вашего модуля) с помощью

sentinel = object()

В противном случае вы можете использовать в роли дозорного любое значение, которое вы «знаете» (исходя из соображений приложения), которое итератор может ' т возможно уступить.

34
ответ дан 24 November 2019 в 06:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: