2010-04-02 4 views
4

Каков правильный способ формирования таблицы in-memory в python с прямым поиском строк и столбцов.
Я думал использовать Dict из dicts этот путь,
Python In-memory table

class Table(dict): 
    def __getitem__(self, key): 
     if key not in self: 
      self[key]={} 
     return dict.__getitem__(self, key) 
table = Table() 
table['row1']['column1'] = 'value11' 
table['row1']['column2'] = 'value12' 
table['row2']['column1'] = 'value21' 
table['row2']['column2'] = 'value22' 
>>>table 
{'row1':{'column1':'value11','column2':'value12'},'row2':{'column1':'value21','column2':'value22'}} 

Я с трудом отрываясь значений в столбцах.

>>>'row1' in table 
True 
>>>'value11' in table['row1'].values() 
True 

Теперь, как я поиск, если 'column1' имеет 'value11'
Является ли этот метод формирования таблиц неправильно?
Есть ли лучший способ реализовать такие таблицы с более легким поиском ?.

+1

Является ли это «редкой таблицей» или каждая ячейка содержит значение? Также будет ли каждое значение уникальным? Вы хотите быстрый поиск значений на основе координат, или наоборот, или и то, и другое? –

+0

Каждая ячейка будет содержать значение. Ценности не обязательно должны быть уникальными. Мне нужно искать значения в обоих направлениях. Это достижимо ?. – asdfg

+0

Какой результат вы хотите, когда ищете значение? Все координаты, в которых он появляется? –

ответ

7

Теперь, как я поиск, если 'column1' имеет 'value11'

any(arow['column1'] == 'value11' for arow in table.iteritems())

Является ли этот способ формирования таблиц неправильно?

Нет, это просто очень «разоблачил», возможно, слишком много - это было бы полезно инкапсулировать в классе, который обнажает методы вам нужно, то вопрос о том, как лучше реализовать их не влияет на все остальное вашей заявки.

Есть ли лучший способ реализовать такие таблицы с более удобными поисками?

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

У меня были похожие, но не идентичные потребности в большом внутреннем приложении, которое я поддерживаю на работе, за исключением того, что индексы строк являются целыми (только имена столбцов являются строками), порядок столбцов важен, а рабочая нагрузка больше о " редактирование "таблицы (добавление, удаление, переупорядочение строк или столбцов, переименование столбцов и т. д.). Я начал с таблицы, раскрывающей необходимые мне функциональные возможности, с простейшей грубой и готовой реализацией внутри (список dicts, а также список имен столбцов для упорядочения столбцов); и к настоящему времени я разработал его (независимо от фактических «частей приложения», но основываясь на профилировании и сравнительном анализе) для совершенно разных реализаций (в настоящее время на основе numpy).

Я думаю, что вам следует продолжить аналогичные строки: «одеть» вашу текущую реализацию в приятный «интерфейс» со всеми необходимыми методами, профилировать приложение - если этот объект таблицы не является узким местом производительности, все готово ; если это является узким местом, вы можете оптимизировать реализацию (эксперимент, измерение, повторить ;-), не нарушая ни одну из остальных приложений.

Унаследовано от dict не очень хорошая идея, потому что вы, вероятно, не хотите раскрывать всю функциональность dict; плюс, то, что вы делаете, грубо говоря, неэффективная реализация collections.defaultdict(dict). Таким образом, инкапсулировать последние:

import collections 

class Table(object): 
    def __init__(self): 
     self.d = collections.defaultdict(dict) 
    def add(self, row, col, val): 
     self.d[row][col] = val 
    def get(self, row, col, default=None): 
     return self.d[row].get(col, default) 
    def inrow(self, row, col): 
     return col in self.d[row] 
    def incol(self, col, val): 
     return any(x[col]==val for x in self.d.iteritems()) 

и т.д., и т.д. - написать все методы ваших потребностей приложений, с полезными, короткими именами, то, возможно, увидеть, если вы можете псевдоним некоторые из них, как специальных методов, если они» повторно часто используется таким образом, например, может быть (в предположении, Python 2. * - требует немного другой синтаксис 3. *):

def __setitem__(self, (row, col), val): 
     self.add(row, col, val) 

и так далее. После того, как вы работаете с кодом, , то подходит для профилирования, бенчмаркинга и, возможно, - внутренней оптимизации реализации.

+0

Спасибо за рекомендации – asdfg

7

Я бы использовал in-memory database с SQLite. Модуль sqlite находится даже в стандартной библиотеке с Python 2.5, что означает, что это даже не добавляет ваших требований.

+0

Что делать, если у меня было тысячи строк. Является ли sqlite лучше, чем использование списков или словарей? – asdfg

+0

Я согласен с Keturn, sqlite - это путь, и снова он не выглядит pythonistic, чтобы попытаться построить таблицу в python. – gath

+0

Как это лучше или лучше, чем использование вложенных типов. Таблица, которую я использую, постоянно меняется. Не слишком много db пишет дорого ?. Спасибо за ответ. – asdfg

0

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

grid = [] 
for row in height: 
    grid.append([]) 
    for cell in width: 
     grid[-1].append(value) 

Проверка строк легко:

def valueInRow(value, row): 
    return value in grid[row] 

Проверка collumns занимает немного больше работы, потому что сетка представляет собой список строк, а не список collumns:

def collumnIterator(collumn): 
    height = len(grid) 
    for row in xrange(height): 
    yield grid[row][collumn] 

def valueInCollumn(value, collumn): 
    return value in collumnIterator(collumn) 
+0

Строки не являются целыми числами, а высота не фиксирована. Кроме того, я могу перебирать строку dicts для проверки значений в столбцах. Я просто хотел знать, можно ли это сделать, избегая итерации. – asdfg

0

Теперь как искать, если «column1» имеет значение «value11»

Вы спрашиваете об этом?

found= False 
for r in table: 
    if table[r]['column1'] == 'value11' 
     found= True 
     break 

Это то, что вы пытаетесь сделать?

+0

Да, но я хотел сделать это, итерации по таблице. Как «строка» в «таблице» – asdfg

+0

«итерирование по таблице»? Что это может означать? –