Игнорирование регистра, пунктуации и пробелов в строках - PullRequest
0 голосов
/ 30 января 2010

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

Я собирался использовать строки, нечувствительные к регистру и пунктуации, для следующего кода, но, увидев, сколько времени потребуется для оценки 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)

Ответы [ 2 ]

2 голосов
/ 30 января 2010

«Как лучше всего решить эту проблему?»

Лучший и единственный способ - определить, что этот объект "означает" и что означает длина этого объекта.

Объект выглядит как список слов. Ничего более. Кажется, это значение в _string.

Не ясно, что такое _simple, кроме недоступного отфильтрованного подмножества слов в _string.

Так какая длина? Длина слов или длина слов в отфильтрованном подмножестве?

Только вы можете определить, что означает этот класс . Значение , означающее , будет определять способ реализации __len__. Пока вы не определите значение, невозможно определить, как что-либо должно быть реализовано.

2 голосов
/ 30 января 2010

Если вы хотите, чтобы итерация для экземпляра String повторялась для его self.__string, как указывает ваш метод __iter__, единственный разумный выбор для длины также должен возвращать длину __string - это будет действительно свойственно, если len(x) и sum(1 for _ in x) приводят к различным значениям.

Должен признать, что я не понимаю цели этого класса (и, в частности, почему вы сделали ужасный выбор иметь его в старом стиле, и почему вы используете такой искаженный способ построения __simple), но внутренняя согласованность важна в любом случае. Так что, либо измените __iter__, либо сделайте __len__ логически совместимым с ним.

Ваша логика нарезки также полностью ускользает от меня - почему вы создаете __simple среза таким образом, который, вероятно, будет отличаться от того, что вы получите, перестраивая его из __string среза? Например, если self.__string - это «Бох!» и, следовательно, self.__simple - это 'boh', почему вы хотите, чтобы self[1:-1] имели __string из 'Boh', но с __simple из 'o', столь несовместимые, разные и несовместим с __simple, который вы получите, если повторно вычислить его из фрагмента ...?

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

...