2010-11-16 3 views
7

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

get_range(dict, begin, end): 
    return {a new dict for all the indexes between begin and end} 

Как это можно сделать?

EDIT: Я не спрашиваю, используя ключ фильтра ... например)

{"a":"b", "c":"d", "e":"f"} 

get_range(dict, 0, 1) returns {"a":"b", "c":"d"} (the first 2 elements) 

Я не забочусь сортировкой ... На самом деле я реализую на стороне сервера подкачки ...

+2

от __indexes__ Вы имеете в виду ключи ??? – mouad

+1

@singularity: глядя на прошлый вопрос OP http://stackoverflow.com/questions/4181367/python-possible-to-filter-dict, вы должны быть правы. – kennytm

+0

НЕТ, не по ключу, сразу после некоторой сортировки (или вообще не сортировки), я хочу, чтобы первая/последняя/средняя части dict ... –

ответ

16

Редактировать: Словарь: не указан. Невозможно сделать get_range возвратом одного и того же фрагмента, когда вы изменили словарь. Если вам нужен детерминированный результат, замените dictwith a collections.OrderedDict.

Во всяком случае, вы могли бы получить кусок using itertools.islice:

import itertools 
def get_range(dictionary, begin, end): 
    return dict(itertools.islice(dictionary.iteritems(), begin, end+1)) 

Предыдущий ответ, который фильтрует ключом хранится ниже:

С @Douglas "алгоритм, мы могли бы упростить с использованием выражения генератора:

def get_range(dictionary, begin, end): 
    return dict((k, v) for k, v in dictionary.iteritems() if begin <= k <= end) 

BTW, не используйте dict как имя переменной, как вы можете видеть здесь. dict - это конструктор словаря.

Если вы используете Python 3.x, вы можете напрямую использовать словарь.

def get_range(dictionary, begin, end): 
    return {k: v for k, v in dictionary.items() if begin <= k <= end} 
+0

Хорошее решение и все еще очень читаемо. – helpermethod

+0

Вызов переменной the_dict или такой «правильный» стиль для переменных. –

+0

@ Крис: Хорошо. (Переименовано в «словарь», так что обе стороны довольны :)) – kennytm

3

прямой реализации:

def get_range(d, begin, end): 
    result = {} 
    for (key,value) in d.iteritems(): 
     if key >= begin and key <= end: 
      result[key] = value 
    return result 

Одна линия:

def get_range2(d, begin, end): 
    return dict([ (k,v) for (k,v) in d.iteritems() if k >= begin and k <= end ]) 
+2

или: __begin <= key <= end__ – mouad

+1

Eek, * пожалуйста * не вызывайте параметр 'dict' ... также' key> = begin и key <= end' будет более аккуратным, поскольку 'begin <= key < = end'. Cool Python, как вы можете это сделать. –

+0

Просто после OP ... Я согласен с неправильным именем переменной. –

0

отдыха уверены, что то, что вы действительно хотите OrderedDict, вы можете также использовать enumerate:

#!/usr/bin/env python 
def get_range(d, begin, end): 
    return dict(e for i, e in enumerate(d.items()) if begin <= i <= end) 

if __name__ == '__main__': 
    print get_range({"a":"b", "c":"d", "e":"f"}, 0, 1) 

выход:

{'a': 'b', 'c': 'd'} 

пс: Я позволяю вам использовать 0, 1 в качестве значений диапазона, но вы должны использовать 0, 2, чтобы подписать «первые два элемента» (и использовать begin <= i < end в качестве функции сравнения

0

Как уже упоминалось, словари Python по своей сути неупорядочены. Однако в любой момент времени список их текущих ключей или пар ключей, значений может быть получен с использованием их методов keys() или items().

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

Чтобы сделать этот подход более управляемым, вы можете комбинировать словарь и вспомогательный список в новый производный класс, который выполняет синхронизацию между ними, а также предоставляет метод get_range(), который использует текущее содержимое списка. Ниже приведен пример кода, показывающего, как это можно сделать. Это основано на идеях, которые я получил от кода в this ActiveState Python Recipe.

class dict_with_get_range(dict): 
    def __init__(self, *args, **kwrds): 
     dict.__init__(self, *args, **kwrds) 
     self._list_ok = False 

    def _rebuild_list(self): 
     self._list = [] 
     for k,v in self.iteritems(): 
      self._list.append((k,v)) 
     self._list_ok = True 

    def get_range(self, begin, end): 
     if not self._list_ok: 
      self._rebuild_list() 
     return dict(self._list[i] for i in range(begin,end+1)) 

def _wrapMutatorMethod(methodname): 
    _method = getattr(dict, methodname) 
    def wrapper(self, *args, **kwrds): 
     # Reset 'list OK' flag, then delegate to the real mutator method 
     self._list_ok = False 
     return _method(self, *args, **kwrds) 
    setattr(dict_with_get_range, methodname, wrapper) 

for methodname in 'delitem setitem'.split(): 
    _wrapMutatorMethod('__%s__' % methodname) 
for methodname in 'clear update setdefault pop popitem'.split(): 
    _wrapMutatorMethod(methodname) 
del _wrapMutatorMethod # no longer needed 

dct = dict_with_get_range({"a":"b", "c":"d", "e":"f"}) 
print dct.get_range(0, 1) 
# {'a': 'b', 'c': 'd'} 
del dct["c"] 
print dct.get_range(0, 1) 
# {'a': 'b', 'e': 'f'} 

Основная идея заключается в том, чтобы получить новый класс из dict, который также имеет внутренний список содержимого для использования нового метода get_range() он предусматривает, что регулярные словарные объекты нет. Чтобы минимизировать необходимость обновления (или даже создания) этого внутреннего списка, у него также есть флаг, указывающий, обновляется ли этот список или нет, и только проверяет его и перестраивает список, когда это необходимо.

Чтобы сохранить флаг, каждый унаследованный метод словаря, который потенциально изменяет (или мутирует) содержимое словаря, «обернут» вспомогательной функцией, сбрасывает флаг, а затем цепочки к нормальному словарному методу для фактической выполнения операции. Установка их в класс - это просто вопрос о назначении имен методов в одном из двух списков, а затем передача их по одному вспомогательной утилите сразу же после создания класса.

Смежные вопросы