2016-05-04 4 views
2

Существует взаимно однозначное соотношение между каждыми двумя столбцами таблицы, например Ci <--> Cj.Как сохранить таблицу отношений один-к-одному для быстрого поиска в Python?

Как хранить такой стол для быстрого поиска? Я четко выскажусь со следующим фрагментом кода.

C1 = [1, 2, 3, 4] 
C2 = ['a', 'b', 'c', 'd'] 
C3 = ['one', 'two', 'three', 'four'] 

# lookup, Ci --> Cj 
idx = Ci.index(val) 
corresponding_val = Cj[idx] 

Dict будет хорошим выбором. Возьмем таблицу с двумя столбцами в качестве примера, сохраните таблицу как dict, скажем d[C1] = C2. Требуется O(1) от C1 до C2. Но от C2 до C1 это займет больше времени.

+0

Как насчет наличия двух диктонов, по одному для каждого пути? Или диктат, который имеет каждую взаимосвязь дважды, по-разному? – ddsnowboard

+0

@ddsnowboard, он работает для двух столбцов. Но для столбцов * n * нам нужно * n * (n-1) * dicts. – SparkAndShine

ответ

4

Если вам нужен быстрый поиск ключа в любом из C1, C2, C3, то три dicts. Значение каждого из них представляет собой 3-кортеж.

all = zip(C1, C2, C3) 
d1,d2,d3 = {},{},{} 
for v in all: 
    d1[ v[0]], d2[v[1]], d3[v[2]] = v,v,v 

Использование:

>>> d3['three'] 
(3, 'c', 'three') 
>>> d1[1] 
(1, 'a', 'one') 
>>> d2['a'] 
(1, 'a', 'one') 

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

assert d1[1] is d2['a'] and d1[1] is d3['one'] 

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

C2=['odd','even','odd','even'] 
... 
for v in all: 
    d1.setdefault(v[0],[]).append(v) 
    d2.setdefault(v[1],[]).append(v) 
    d3.setdefault(v[2],[]).append(v) 

>>> d2 
{'even': [(2, 'even', 'two'), (4, 'even', 'four')], 'odd': [(1, 'odd', 'one'), (3, 'odd', 'three')]}  
+1

Может быть полезно объединить все ключи в один словарь. Измените назначение на 'd [v [0]], d [v [1]], d [v [2]] = v'. В этом случае вам нужно выполнить только 'd [C1 [i]]' или 'd [C2 [i]]' или 'd [C3 [i]]'. –

+0

@John Carpenter Да, это будет работать до тех пор, пока не будет дублированных значений при слиянии всех столбцов. Если есть, то он по-прежнему работает, если вы используете 'setdefault' для создания списка, и, получив все соответствующие строки, проверьте, соответствует ли совпадение правильному столбцу или нет. – nigel222

1

Как насчет того, чтобы закрепить все столбцы в уникальном списке. Вид:

D = zip(C1, C2, C3,...) 

Таким образом, вы можете цикл по первому элементу D и возвращает другим, что вам нужно, используя список comprehesion.

+1

«Быстрый поиск» означает что-то лучше, чем линейный поиск: хеш-таблица, что и предоставляет dict. Поиск - O (N). Таблица хэша O (1) или в худшем случае для больших N, O (ln N). – nigel222

+0

Yep @ nigel222. Я забыл об этом, моя вина. Действительно, использование хэша всегда будет лучше ... Итак, что может быть приемлемым решением без использования хэша? Он использует алгоритм для упорядочения списка (сортировка двоичного дерева ...), тогда вы можете использовать другой алгоритм для поиска результатов, ... Ваши затраты могут быть более чем приемлемыми, если вам нужно выполнить несколько поисков ... O (n log n) (один раз) и O (log n). –

+1

Если вы используете Python и все вписывается в память, просто используйте dict и полагайтесь на людей, которые разрабатывают Python, выбрали хорошие алгоритмы хеширования и внутренние структуры данных. Без Python ... ну, я однажды использовал 16-битное хэш-значение для выбора из одного из списков 64K. Большинство значений хэша обратились к одному элементу списка, потому что было около 40 000 вещей для индексации.Единственная причина, по которой я должен был сворачивать сам, был ли это древний код Fortran, который использовался сильнее, чем ожидали его первоначальные программисты. В общем, есть уже код библиотеки! – nigel222