Структура данных Python для индексируемого списка строк

#python #algorithm #data-structures

#python #алгоритм #структуры данных

Вопрос:

Я получил список объектов, которые выглядят как строки, но не являются реальными строками (подумайте о файлах mmap’ed). Вот так:

 x = [ "abc", "defgh", "ij" ]
  

То, что я хочу, x должно быть напрямую индексируемым, как будто это была большая строка, т. Е.:

 (x[4] == "e") is True
  

(Конечно, я не хочу делать «».join(x), который объединил бы все строки, потому что чтение строки в моем случае слишком дорого. Помните, что это файлы mmap.).

Это легко, если вы выполняете итерацию по всему списку, но, похоже, это O (n). Итак, я реализовал __getitem__ более эффективно, создав такой список:

 x = [ (0, "abc"), (3, "defgh"), (8, "ij") ]
  

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

Я вижу, как реализовать __setitem__ , но это кажется таким скучным, мне интересно, нет ли чего-то, что уже делает это.

Чтобы быть более точным, это то, как структура данных должна соответствовать __setitem__ :

 >>> x = [ "abc", "defgh", "ij" ]
>>> x[2:10] = "12345678"
>>> x
[ "ab", "12345678", "j" ]
  

Я бы принял любую идею о такой реализации структуры данных, имени или любом намеке.

Комментарии:

1. «Конечно, я не хочу делать «».join(x), который объединил бы все строки?» Почему бы и нет? «чтение строки в моем случае слишком дорого» Какое это имеет отношение к чему-либо? Что — именно — не так с объединением?

2. Потому что строки в списке на самом деле не являются строками. Это (своего рода) файлы mmap’ed. Но они просто работают как строки (они реализуют __getitem__ ).

3. x[4] == e, потому что __getitem__ перегружен в x классе (подкласс list).

4. @Woot4Moo: Если вы объединили все строки в одну, ‘e’ находится с индексом 4.

5. @jd_: «строки в списке на самом деле не являются строками». Тогда, пожалуйста, исправьте вопрос, чтобы указать, что это такое на самом деле. Прямо сейчас вопрос вводит в заблуждение.

Ответ №1:

То, что вы описываете, является частным случаем веревочной структуры данных.

К сожалению, я не знаю ни о каких реализациях Python.

Комментарии:

1. Спасибо за ссылку! Действительно, это действительно похоже на это. 🙂

2. PyPy реализует структуру данных rope, не так ли? — morepypy.blogspot.com/2007/11/ropes-branch-merged.html

Ответ №2:

Вы воссоздали тип данных словаря.

Комментарии:

1. Не совсем так. В словаре вы не можете тривиально найти символ в позиции, i если i он не является началом одной из подстрок.

2. Не каждый ключ соответствует непосредственно одной из строк в его списке. Если вы имеете в виду, что концептуально это словарь, это также неверно, поскольку не может быть никакого i между 0 и len(op_s_object) s.t. op_s_object[i] не имеет значения.

3. В объяснении op чего-то не хватает, например, ему еще предстоит объяснить, как x [4] == e. Переопределяет ли он значение equals в значении contains:?

4. «То, что я хочу, x чтобы оно было напрямую индексируемым, как большая строка» — я так понимаю, это означает, что он создает тип последовательности, то есть строку другими способами.

5. почему бы просто не использовать массив символов, в котором уже есть поиск O (1). Или, возможно, его O (n) я забыл.

Ответ №3:

Итак, вы все еще хотите иметь возможность обращаться к n-му элементу списка вообще, например, найти это x.somemethod(2) == 'ij' ? Если нет, то ваша структура данных — это просто строка с некоторыми методами, позволяющими сделать ее изменяемой и инициализировать ее из списка строк.

Если вы действительно хотите иметь такую возможность, то ваша структура данных по-прежнему представляет собой строку с этими дополнительными методами, плюс еще один элемент для отслеживания диапазонов, из которых были взяты его элементы, например x.camefrom(1) == (3, 7) .

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

Комментарии:

1. Вы пропустили ту часть, где я написал «Я не хочу читать строку». Если я вас правильно понимаю, создание строки, инициализированной из списка string, означает чтение всех строк и их копирование. 🙂

2. Я не пропустил это. Я проигнорировал это, потому что это звучало так, как будто вы делаете вещи намного сложнее, чем вам нужно, не объясняя, почему вы хотите сделать это сложным способом. 🙂

Ответ №4:

Это может быть началом:

 self._h = {0:"abc", 3:"defgh", 8:"ij"} #create _h and __len__ in __init__
self.__len__ = 10

def __getitem__(i):
    if i >= self.__len__:
        raise IndexError
    o=0
    while True:
        if i-o in self._h:
            return self._h[i-o][o]
        o =1
  

улучшения содержат изменчивость.

Ответ №5:

Я не знаю ничего, что делает то, что вы хотите.

Однако, если вы __getitem__ эффективно реализовали то, как вы говорите, то у вас уже есть код, который сопоставляет индекс вашему кортежу, списку строк. Поэтому кажется, что вы могли бы просто повторно использовать этот фрагмент кода — с небольшим рефакторингом — для реализации, __setitem__ которой требуется та же информация для выполнения своей функции.