2014-12-31 3 views
8

У меня есть collections.OrderedDict со списком пар ключей, значений. Я хотел бы вычислить индекс i так, что i-й ключ соответствует заданному значению. Например:Получение ключевого индекса в Python OrderedDict?

food = OrderedDict([('beans',33),('rice',44),('pineapple',55),('chicken',66)]) 

Я хочу, чтобы перейти от ключа chicken к индексу 3, или от ключа rice к индексу 1. Я могу сделать это сейчас с

food.keys().index('rice') 

но есть каким-либо образом использовать способность OrderedDict быстро просмотреть информацию по ключевому названию? Иначе кажется, что поиск индекса будет O (N), а не O (log N), и у меня много элементов.

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

>>> foodIndex = {k:i for i,k in enumerate(food.keys())} 
>>> foodIndex 
{'chicken': 3, 'rice': 1, 'beans': 0, 'pineapple': 2} 

, но я надеялся, что там может быть что-то встроенное в качестве OrderedDict.

ответ

12

В принципе, нет. OrderedDict получает свою способность быстро искать вещи по ключевым словам, просто используя обычный, неупорядоченный dict под капотом. Информация о заказе хранится отдельно в двусвязном списке. Из-за этого невозможно перейти непосредственно от ключа к его индексу. Заказ в OrderedDict предназначен в основном для итерации; ключ не «знает» собственный порядок.

3

The OrderedDict является подклассом dict, который имеет возможность перемещать свои ключи по порядку (и обратному порядку) на maintaining a doubly linked list. Значит, он не знает индекса ключа. Он может пересекать связанный список только для поиска элементов в O (n) времени.

Perusing the source code может быть наиболее подходящим, чтобы подтвердить, что индекс не поддерживается OrderedDict. Вы увидите, что нет, где индекс, когда-либо используемый или полученный.

2

Как указывали другие, OrderedDict - это просто словарь, который внутренне запоминает, какие записи заказов были добавлены к нему. Тем не менее, вы можете использовать свою способность быстро искать вещи, сохраняя желаемый индекс вместе с остальными данными для каждой записи. Вот что я имею в виду:

from collections import OrderedDict 

foods = [('beans', 33), ('rice', 44), ('pineapple', 55), ('chicken', 66)] 
food = OrderedDict(((v[0], (v[1], i)) for i, v in enumerate(foods))) # saves i 

print(food['rice'][1]) # --> 1 
print(food['chicken'][1]) # --> 3 
+1

Вы можете сделать это, но оно не будет храниться в синхронизации, если вы добавите и/или удалите элементы. – BrenBarn