#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__
которой требуется та же информация для выполнения своей функции.