2010-01-30 118 views
0

什麼是忽略字符串中的大小寫字母,標點符號和空白字符的最有效方法?這些字符串應該被分成單詞而不是字符,應該忽略前面提到的比較細節,並且這些字串的切片應該儘可能高效地記住速度。忽略字符串中的大小寫,標點符號和空白字符

我打算在下面的代碼中使用大小寫不敏感的字符串,但看到評估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) 
+0

如果有一些上下文/文檔是關於什麼類用於... – 2010-01-30 19:54:30

+0

請不要使用'__'作爲你的「私人」變量名稱。請使用'_':這是更常見的,並且減少我們的大腦閱讀代碼的壓力。 – 2010-01-30 20:25:03

+1

我有點困惑;什麼是問題? – mithrandi 2010-01-31 03:15:55

回答

2

「什麼是最好的路要走關於解決這個問題?「

最好的唯一的方法是定義這個對象「意味着什麼」以及這個對象的長度是什麼意思。

該對象似乎是一個單詞列表。而已。這似乎是_string中的值。

目前還不清楚_simple是什麼,除了在_string中的字不可訪問的過濾子集。

那麼長度是多少?單詞的長度或過濾子集中單詞的長度?

只有您可以定義此類意味着。然後含義將確定如何實施__len__。在定義含義之前,不可能確定應該如何實施。

2

如果你想在一個String實例迭代遍歷其self.__string,爲您__iter__方法表明,對於長度唯一明智的選擇也是迴歸的__string長度 - 這將是真正奇特如果len(x)sum(1 for _ in x)導致不同的值。

我不得不承認,我不明白這個班的目的(特別是爲什麼你做了這個老式的可怕選擇,爲什麼你用這種扭曲的方式來構建__simple),但內部反正一貫性很重要。因此,要麼改變__iter__,要麼使__len__在邏輯上與它兼容。

你的切片邏輯也完全逃脫我 - 你爲什麼要以這種方式構建切片的__simple,這種方式可能與通過從切片的__string重建切片所得到的方式不同?例如,如果self.__string是'?Boh!'因此self.__simple是'boh',你爲什麼要想要self[1:-1]有一個'Boh'的__string但是'__simple'爲'o',所以與__simple不兼容,不同和不一致,通過重新計算得到切片......?

我想這是不有密切關係這種問答關於長度,但我只是好奇你正在做的是,這些很多,非常奇特的設計選擇......

+0

自從Python 3.0問世以來,我只用這種語言編寫代碼(目前是3.1)。如果您熟悉3.1中的類是如何工作的,那麼您知道這是一種新式類(Python 3.x中的所有類都是新類)。因此,沒有必要顯式繼承'object'。至於切片是如何工作的,請注意以下這行:'self .__ string = tuple(string.split())'這些字符串對象對字而不是字符起作用。 – 2010-01-31 03:21:54

+0

@Noctis,你已經徹底改變了代碼(例如,我再沒有看到任何String類!),我無法將我的註釋重新連接到當前代碼。對於Python 3來說,這很好,但在你的Q中提到它顯然會更好,因爲*不是*今天絕大多數Python用戶正在使用的;-)。 – 2010-01-31 05:27:10