Игнорирование случая, пунктуации и пробелы в струнах
Вопрос
Какой самый эффективный способ игнорирования случая, пунктуации и пробела в строках? Эти строки следует разделить словами вместо персонажей, следует игнорировать вышеупомянутые детали на сравнениях, а ломтики этих слов-строк должны быть максимально эффективными со скоростью со скоростью.
Я собирался использовать корпус и пременную нечувствительные строки для следующего кода, но после просмотра, сколько времени потребуется для оценки class Slice: def __eq__(self, other): return self.root == other.root
, Я решил работать с data = tuple(string.split())
вместо. Наличие струн, которые нечувствительны к корпусу, пунктуации и интервале, и которые работают над словами вместо персонажей, были слишком дорогими в вычисленные дорогие алгоритмы, уже выраженные в коде ниже.
class Slice:
def __init__(self, data, offset, length):
self.prefix = data[:offset]
self.root = data[offset:offset+length]
self.suffix = data[offset+length:]
def __eq__(self, other):
return self.root == other.root
def __len__(self):
return len(self.root)
################################################################################
class Match:
def __init__(self, data, key, prefix_tree, suffix_tree):
self.data = data
self.key = key
self.prefix_tree = prefix_tree
self.suffix_tree = suffix_tree
self.__value = len(key) + prefix_tree.value() + suffix_tree.value()
def value(self):
return self.__value
################################################################################
class Tree(tuple):
def __new__(cls, nodes):
tree = super().__new__(cls, nodes)
tree.__value = max(map(Match.value, tree)) if tree else 0
return tree
def value(self):
return self.__value
def find(self, value):
for index, match in enumerate(self):
if match.value() == value:
return index
raise ValueError()
################################################################################
def search(data, key):
length = 0
nodes = []
for d_block in shrink(data, len(key)):
block_len = len(d_block)
if length > block_len:
return Tree(nodes)
for k_block in slide(key, block_len):
if d_block == k_block:
length = block_len
prefix_tree = search(d_block.prefix, k_block.prefix)
suffix_tree = search(d_block.suffix, k_block.suffix)
match = Match(d_block, k_block, prefix_tree, suffix_tree)
nodes.append(match)
return Tree(nodes)
def shrink(data, max_len):
for length in range(min(len(data), max_len), 0, -1):
for block in slide(data, length):
yield block
def slide(data, length):
for offset in range(len(data) - length + 1):
yield Slice(data, offset, length)
################################################################################
def build_tree(nodes):
match = nodes[nodes.find(nodes.value())]
node = match.key
if match.prefix_tree:
node.prefix = build_tree(match.prefix_tree)
if match.suffix_tree:
node.suffix = build_tree(match.suffix_tree)
return node
def flatten_tree(node):
array = [0]
_flatten(node, array)
return tuple(array)
def _flatten(node, array):
if isinstance(node.prefix, Slice):
_flatten(node.prefix, array)
else:
array.append(node.prefix)
array[0] += 1
array.append((array[0], node.root))
if isinstance(node.suffix, Slice):
_flatten(node.suffix, array)
else:
array.append(node.suffix)
Решение
«Какой лучший способ понять эту проблему?»
Лучший - и только - путь - это определить, что этот объект «означает» и какая длина этого объекта «означает».
Объект, по-видимому, является список слов. Больше ничего. Это кажется ценностью в _string
.
Это не ясно, что _simple
это, кроме недоступного фильтрованного подмножества слов в _string
.
Так в чем же длина? Длина слова или длина слов в отфильтрованном подмножестве?
Только вы можете определить, что этот класс означает. Отказ То имея в виду Затем определите, как реализовать __len__
. Отказ Пока вы не определите смысл, невозможно определить, как все должно быть реализовано.
Другие советы
Если вы хотите итерацию на строке экземпляра, чтобы повторить его self.__string
, как твой __iter__
Способ указывает, единственный разумный выбор для длины также для возврата длины __string
-- это было бы действительно свойственный, если len(x)
а также sum(1 for _ in x)
привело к разным ценностям.
Я должен признать, что я не понимаю цели этого класса (и, в частности, почему вы сделали ужасный выбор наличия его старого стиля, и почему вы используете такой арендуемый способ построить __simple
), но внутренняя консистенция важна в любом случае. Итак, либо изменить __iter__
, или сделать __len__
логически совместим с этим.
Ваша логика нарезки также полностью избегает - почему вы строите ломтик __simple
таким образом, что, вероятно, отличается от того, что вы получите, восстановив его с ломтика __string
? Например, если self.__string
'? BOH!' и поэтому self.__simple
это «бо», почему бы вы хочу self[1:-1]
иметь __string
«БО», но с __simple
«о», так несовместимых, разных и несовместимых от __simple
Вы бы пересматривали его с ломтика ...?
Я думаю, это не герман к этому q о длине, но мне просто интересно эти многочисленные, чрезвычайно своеобразные варианты дизайна, которые вы делаете ...