В Python, как я могу получить следующий и предыдущий ключ: значение определенного ключа в словаре?

Хорошо, так что это немного сложно объяснить, но здесь идет:

У меня есть словарь, к которому я добавляю контент. Содержимое - хэшированное имя пользователя (ключ) с IP-адресом (значением). Я помещал хеши в порядок, запуская их против базы 16, а затем используя Collection.orderedDict. Итак, словарь выглядел примерно так:

d = {'1234': '8.8.8.8', '2345':'0.0.0.0', '3213':'4.4.4.4', '4523':'1.1.1.1', '7654':'1.3.3.7', '9999':'127.0.0.1'}

Мне нужен был механизм, который позволил бы мне выбрать один из этих ключей и получить элемент ключ/значение один выше и один ниже. Так, например, если бы я должен был выбрать 2345, код вернул бы ключ: комбинации значений "1234: 8.8.8.8" и "3213: 4.4.4.4"

Итак, что-то вроде:

for i in d:
  while i < len(d)
   if i == '2345':
     print i.nextItem
     print i.previousItem
     break()

Ответ 1

Как видно из OrderedDict исходного кода, если у вас есть ключ, и вы хотите найти следующий и prev в O (1) здесь, как вы это делаете.

>>> from collections import OrderedDict
>>> d = OrderedDict([('aaaa', 'a',), ('bbbb', 'b'), ('cccc', 'c'), ('dddd', 'd'), ('eeee', 'e'), ('ffff', 'f')])
>>> i = 'eeee'
>>> link_prev, link_next, key = d._OrderedDict__map['eeee']
>>> print 'nextKey: ', link_next[2], 'prevKey: ', link_prev[2]
nextKey:  ffff prevKey:  dddd

Это даст вам следующий и предыдущий порядок вставки. Если вы добавляете элементы в произвольном порядке, просто отслеживайте свои товары в отсортированном порядке.

Ответ 2

Изменить: OP теперь заявляет, что они используют OrderedDicts, но прецедент по-прежнему требует такого подхода.

Поскольку dicts не упорядочены, вы не можете напрямую это сделать. В вашем примере вы пытаетесь ссылаться на элемент, как если бы вы использовали связанный список.

Быстрое решение заключалось бы в том, чтобы извлечь ключи и отсортировать их, а затем перебрать этот список:

keyList=sorted(d.keys())
for i,v in enumerate(keyList):
    if v=='eeee':
        print d[keyList[i+1]]
        print d[keyList[i-1]]

keyList хранит порядок ваших товаров, и вам нужно вернуться к нему, чтобы узнать, что следующий/предыдущий ключ должен получить следующее/предыдущее значение. Вы также должны проверить, что я + 1 больше длины списка, а i-1 меньше 0.

Аналогичным образом вы можете использовать OrderedDict, но я считаю, что вам все равно нужно сделать это с помощью отдельного списка, поскольку у OrderedDict нет методов next/prev.

Ответ 3

Try:

pos = 0
d = {'aaaa': 'a', 'bbbb':'b', 'cccc':'c', 'dddd':'d', 'eeee':'e', 'ffff':'f'}

for i in d:
    pos+=1
    if i == 'eeee':
        listForm = list(d.values())
        print(listForm[pos-1])
        print(listForm[pos+1])

Как и в ответе @AdamKerz enumerate кажется pythonic, но если вы новичок, этот код может помочь вам понять его простым способом.

И я думаю, что он быстрее + ​​меньше по сравнению с сортировкой, а затем строит список, а затем перечисляет

Ответ 4

Вы также можете использовать метод list.index().

Эта функция более общая (вы можете проверить позиции + n и -n), она будет пытаться найти ключ, который не находится в dict, и он также вернет None, если ничего не было после ключа

def keyshift(dictionary, key, diff):
    if key in dictionary:
        token = object()
        keys = [token]*(diff*-1) + sorted(dictionary) + [token]*diff
        newkey = keys[keys.index(key)+diff]
        if newkey is token:
            print None
        else:
            print {newkey: dictionary[newkey]}
    else:
        print 'Key not found'


keyshift(d, 'bbbb', -1)
keyshift(d, 'eeee', +1)

Ответ 5

Возможно, это перебор, но вы можете сохранить Track Keys, вставленный с помощью класса Helper, и в соответствии с этим списком вы можете получить ключ для предыдущего или следующего. Просто не забудьте проверить граничные условия, если объекты уже являются первым или последним элементом. Таким образом, вам не нужно всегда прибегать к упорядоченному списку или искать элемент.

from collections import OrderedDict

class Helper(object):
    """Helper Class for Keeping track of Insert Order"""
    def __init__(self, arg):
        super(Helper, self).__init__()

    dictContainer = dict()
    ordering = list()

    @staticmethod
    def addItem(dictItem):
        for key,value in dictItem.iteritems():
            print key,value
            Helper.ordering.append(key)
            Helper.dictContainer[key] = value

    @staticmethod
    def getPrevious(key):
        index = (Helper.ordering.index(key)-1)
        return Helper.dictContainer[Helper.ordering[index]]


#Your unordered dictionary
d = {'aaaa': 'a', 'bbbb':'b', 'cccc':'c', 'dddd':'d', 'eeee':'e', 'ffff':'f'}

#Create Order over keys
ordered = OrderedDict(sorted(d.items(), key=lambda t: t[0]))

#Push your ordered list to your Helper class
Helper.addItem(ordered)


#Get Previous of    
print Helper.getPrevious('eeee')
>>> d

Ответ 6

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

import itertools

def window(iterable, n=3):
    it = iter(iterable)
    result = tuple(itertools.islice(it, n))
    if len(result) == n:
        yield result
    for element in it:
        result = result[1:] + (element,)
        yield result

l = range(8)
for i in window(l, 3):
    print i

Использование вышеуказанной функции с OrderedDict.items() даст вам три пары (ключ, значение) в следующем порядке:

d = collections.OrderedDict(...)

for p_item, item, n_item in window(d.items()):
    p_key, p_value = p_item
    key, value = item
    # Or, if you don't care about the next value:
    n_key, _ = n_item

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

Я думаю, что самым большим преимуществом является то, что он не требует поиска таблиц в предыдущем и последующих ключах, а также что он является общим и работает с любым итерабельным.

Ответ 7

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

Это довольно динамично, будет работать для любой запрошенной вами клавиши. Проверьте этот код:

d = {'1234': '8.8.8.8', '2345':'0.0.0.0', '3213':'4.4.4.4', '4523':'1.1.1.1', '7654':'1.3.3.7', '9999':'127.0.0.1'}
ch = raw_input('Pleasure Enter your choice : ')
keys = d.keys()
values = d.values()
#print keys, values
for k,v in d.iteritems():
    if k == ch:
        ind = d.keys().index(k)
        print keys[ind-1], ':',values[ind-1]
        print keys[ind+1], ':',values[ind+1]