Frage

Was ist die effizienteste Art, Fall, Zeichensetzung und Whitespace in Saiten zu ignorieren? Diese Saiten sollten in Wörter anstelle von Zeichen unterteilt werden, sollten die oben genannten Details zu Vergleiche ignorieren, und die Scheiben dieser Wortschläge sollten unter Berücksichtigung der Geschwindigkeit so effizient wie möglich sein.

Ich wollte für den folgenden Code in den folgenden Code eingesetzt und untersucht, aber nachdem ich festgestellt hatte, wie lange es dauern würde, um zu bewerten class Slice: def __eq__(self, other): return self.root == other.root, Ich habe beschlossen, mit zu arbeiten data = tuple(string.split()) stattdessen. Die Säden, die unempfindlich gegenüber Fall, Interpunktion und Abstand sind und die über Wörter anstelle von Charakteren arbeiten, war zu teuer in den rechnerisch teuren Algorithmen, die bereits im folgenden Code ausgedrückt wurden.

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)
War es hilfreich?

Lösung

"Was ist der beste Weg, um dieses Problem zu beheben?"

Das Beste - und nur - ist zu definieren, was dieses Objekt "bedeutet" und was die Länge dieses Objekts "bedeutet".

Das Objekt scheint eine Liste von Wörtern zu sein. Nichts mehr. Das scheint der Wert in zu sein _string.

Es ist nicht klar was _simple IS, außer einer unzugänglichen gefilterten Teilmenge der Wörter in _string.

Also, was ist die Länge? Die Länge der Wörter oder die Länge der Wörter in der gefilterten Teilmenge?

Nur Sie können definieren, was diese Klasse meint. Das Bedeutung bestimmt dann, wie man implementiert __len__. Bis Sie die Bedeutung definieren, ist es unmöglich zu bestimmen, wie etwas implementiert werden sollte.

Andere Tipps

Wenn Sie eine Iteration auf einer String -Instanz sein möchten, um sich auf seine zu iterieren self.__string, wie dein __iter__ Die Methode zeigt an, dass die einzige sinnvolle Wahl für die Länge auch die Länge von zurückgibt __string -- es wäre wirklich eigenartig, wenn len(x) und sum(1 for _ in x) führte zu unterschiedlichen Werten.

Ich muss zugeben, ich verstehe den Zweck dieser Klasse nicht __simple), aber interne Konsistenz ist sowieso wichtig. Also ändern sich entweder __iter__, oder machen __len__ Logisch kompatibel damit.

Ihre Schnittlogik entgeht mir auch völlig - warum bauen Sie die Slice auf __simple Auf eine Weise, die sich wahrscheinlich von dem unterscheid __string? ZB, wenn self.__string ist '? Boh!' und deshalb self.__simple ist 'boh', warum würdest du? wollen self[1:-1] Ein ... Haben __string von 'boh' aber mit einem __simple von 'o', so inkompatibel, anders und inkonsistent von der __simple Sie würden es durch die Neuzunahme aus der Scheibe bekommen ...?

Ich denke, das ist nicht für dieses Q über Länge, aber ich bin nur neugierig auf diese vielen, extrem merkwürdigen Designentscheidungen, die Sie treffen ...

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top