1

'toy'Trie実装用のイテレータを作成したいと思います。

追加はすでに次のように機能します。

class Trie:
    def __init__(self):
        self.root = dict()
        pass
    def add(self, string, value):
        global nops
        current_dict = self.root
        for letter in string:
           nops += 1
           current_dict = current_dict.setdefault(letter, {})
        current_dict = current_dict.setdefault('value', value)              
        pass

追加の出力は次のようになります。

trie = Trie()
trie.add("hello",1)
trie.add("world",2)
trie.add("worlds",12)
print trie.root
{'h': {'e': {'l': {'l': {'o': {'value': 1}}}}}, 'w': {'o': {'r': {'l': {'d': {'s': {'value': 12}, 'value': 2}}}}}}

私は、メソッドが必要であることを知っます__iter__next

def __iter__(self):
    self.root.__iter__()
    pass

 def next(self):
    print self.root.next()

しかしAttributeError: 'dict' object has no attribute 'next'。どうすればいいですか?

[更新]完璧な世界では、すべての単語/エントリとそれに対応する値を含む1つの辞書を出力にしたいと思います。

4

2 に答える 2

2

__iter__特別なメソッドはイテレータを返す必要があります; つまり、呼び出すことができるクラスのオブジェクトですnext。おもちゃのイテレータクラスは次のようになります。

class MyIterator:
    def __init__(self):
        self.i = 10
    def next(self):
        self.i -= 1
        if self.i == 0:
            raise StopIteration
        else:
            return self.i

呼び出す自然なオブジェクトがない限り、通常はジェネレーターを作成するiter方が簡単です。__iter__

def __iter__(self):
    for i in range(10)
        yield i

これがあなたのためのスタックベースのジェネレータイテレータですTrie

    def __iter__(self):
        stack = [('', self.root)]
        while stack:
            prefix, d = stack.pop()
            for k, v in d.items():
                if k == 'value':
                    yield prefix, v
                else:
                    stack.append((prefix + k, v))

itertools.chainまたはを使用する必要がありますがyield from(Python 3.3以降のみ)、再帰的に記述してみることもできます。

于 2012-11-14T16:52:23.360 に答える
0

イテレータで探しているものを正しく理解していると仮定すると、これらの線に沿って何かを実行します(次のフィールドに追加されていることに注意してください)__init__

class Trie:
    def __init__(self):
        self.root = dict()
        self.stack = ''

    def add(self, string, value):
        """map it to the given value."""
        global nops
        current_dict = self.root
        for letter in string:
           nops += 1
           current_dict = current_dict.setdefault(letter, {})
        current_dict = current_dict.setdefault('value', value)              
        pass

    def __iter__(self, input_dict=None):
        if not input_dict:
            input_dict = self.root

        if 'value' in input_dict:
            yield (self.stack, input_dict['value'])

        keys = [x for x in input_dict.keys() if x != 'value']
        for key in keys:
            self.stack += key
            for item in self.__iter__(input_dict[key]):
                yield item
            self.stack = self.stack[:-1]

それはあなたに与えるでしょう:

trie = Trie()
trie.add("hello", 1)
trie.add("world", 2)
trie.add("worlds", 12)
print trie.root
print [x for x in trie]

# {'h': {'e': {'l': {'l': {'o': {'value': 1}}}}}, 'w': {'o': {'r': {'l': {'d': {'s': {'value': 12}, 'value': 2}}}}}}
# [('hello', 1), ('world', 2), ('worlds', 12)]

itertools.chainしたがって、またはを使用せずにこれを再帰的に実行することができyield fromます。

于 2012-11-14T17:31:50.907 に答える