Самый короткий способ получить первый элемент `OrderedDict` в Python 3

Какой самый короткий способ получить первый элемент OrderedDict в Python 3?

Мое лучшее:

list(ordered_dict.items())[0]

Довольно длинный и уродливый.

Я могу думать:

next(iter(ordered_dict.items()))       # Fixed, thanks Ashwini

Но это не очень самоописано.

Любые лучшие предложения?

Ответы

Ответ 1

Практика программирования для Readabililty

В общем, если вы чувствуете, что код не является самоописанием, обычное решение состоит в том, чтобы разделить его на хорошо названную функцию:

def first(s):
    '''Return the first element from an ordered collection
       or an arbitrary element from an unordered collection.
       Raise StopIteration if the collection is empty.
    '''
    return next(iter(s))

С помощью вспомогательной функции следующий код становится очень читаемым:

>>> extension = {'xml', 'html', 'css', 'php', 'xhmtl'}
>>> one_extension = first(extension)

Шаблоны для извлечения одного значения из коллекции

Обычными способами получения элемента из набора, dict, OrderedDict, генератора или другой неиндексируемой коллекции являются:

for value in some_collection:
    break

и

value = next(iter(some_collection))

Последнее хорошо, потому что функция next() позволяет указать значение по умолчанию, если коллекция пуста, или вы можете позволить ей создать исключение. Функция next() также явна, что запрашивает следующий элемент.

Альтернативный подход

Если вам действительно нужны индексирование и нарезка и другое поведение последовательности (например, индексирование нескольких элементов), просто преобразовать в список с помощью list(some_collection) или использовать [itertools.islice()][2]:

s = list(some_collection)
print(s[0], s[1])

s = list(islice(n, some_collection))
print(s)

Ответ 2

Используйте popitem(last=False), но имейте в виду, что он удаляет запись из словаря, т.е. является разрушительным.

from collections import OrderedDict
o = OrderedDict()
o['first'] = 123
o['second'] = 234
o['third'] = 345

first_item = o.popitem(last=False)
>>> ('first', 123)

Для более подробной информации, посмотрите руководство по коллекциям. Это также работает с Python 2.x.

Ответ 3

Подклассификация и добавление метода к OrderedDict будет ответом на проблемы с ясностью:

>>> o = ExtOrderedDict(('a',1), ('b', 2))
>>> o.first_item()
('a', 1)

Реализация ExtOrderedDict:

class ExtOrderedDict(OrderedDict):
    def first_item(self):
        return next(iter(self.items()))

Ответ 4

Код, который читается, оставляет OrderedDict без изменений и не создает ненужный потенциально большой список только для того, чтобы получить первый элемент:

for item in ordered_dict.items():
    return item

Если order_dict пусто, None будет возвращено неявно.

Альтернативная версия для использования внутри кода:

for first in ordered_dict.items():
    break  # Leave the name 'first' bound to the first item
else:
    raise IndexError("Empty ordered dict")

Код Python 2.x, соответствующий первому примеру выше, должен использовать вместо него iteritems():

for item in ordered_dict.iteritems():
    return item

Ответ 5

Рекомендуемое решение next(iter(s)) работает для конкретного случая, когда вы хотите извлечь первое значение итерируемого. Если ваша итерация имеет известную длину, вы можете обобщить, чтобы извлечь n-е значение:

def get_nth_item(it, n=0):
    if n < 0:
        n += len(it)
    for index, item in enumerate(it):
        if index == n:
            return item
    raise IndexError(f'Iterable index {n} out of range')

Это четкий способ прояснить намерение, поддерживая отрицательные индексы и обрабатывая ошибки, когда предоставляется неправильный индекс. Пример использования с OrderedDict:

from collections import OrderedDict

od = OrderedDict([(1, 'a'), (2, 'b'), (3, 'c')])

get_nth_item(od.items(), n=0)   # (1, 'a')
get_nth_item(od.items(), n=-1)  # (3, 'c')
get_nth_item(od.items(), n=3)   # IndexError: Iterable index 3 out of range

Ответ 6

Первая запись:

[key for key, value in ordered_dict][0]

Последняя запись:

[key for key, value in ordered_dict][-1]

Ответ 7

first = next #<hide this somewhere
first(ordered_dict.iteritems())