これは、混合型 (リスト、タプル、および文字列) の可変長 (長さがゼロの場合もある) シーケンスを処理できる別の回答です。
class EOS(object): pass # end-of-sequence marker
EOS = EOS() # singleton instance
class SeqID(object):
""" Create or find a unique ID number for a given sequence. """
class TreeNode(dict):
""" Branch or leaf node of tree """
def __missing__(self, key):
ret = self[key] = self.__class__()
return ret
def __init__(self, first_ID=1):
self._next_ID = first_ID
self._root = self.__class__.TreeNode()
def __getitem__(self, seq):
# search tree for a leaf node corresponding
# to given sequence and creates one if not found
node = self._root
for term in seq:
node = node[term]
if EOS not in node: # first time seq encountered?
node[EOS] = self._next_ID
self._next_ID += 1
return node[EOS]
elements = [
[ [1, 2], [1, 3], [2, 1], [3, 1], [4, 2] ],
[ [], [2, 1], [4, 3], [3, 4], (1, 3) ],
[ [2, 2], [9, 5, 7], [1, 2], [2, 1, 6] ],
[ 'ABC', [2, 1], [3, 4], [2, 3], [9, 5, 7] ]
]
IDs = SeqID(1000)
print '['
for row in elements:
print ' [ ',
for seq in row:
print '%r: %s,' % (seq, IDs[seq]),
print ' ],'
print ']'
テストケースに示されている多次元配列の要素を使用すると、例に似ていますが、いくつか追加されているため、次の出力が生成されます。生成された ID 番号1000
は、出力で見つけやすくするために強制的に開始されていることに注意してください。
[
[ [1, 2]: 1000, [1, 3]: 1001, [2, 1]: 1002, [3, 1]: 1003, [4, 2]: 1004, ],
[ []: 1005, [2, 1]: 1002, [4, 3]: 1006, [3, 4]: 1007, [1, 3]: 1001, ],
[ [2, 2]: 1008, [9, 5, 7]: 1009, [1, 2]: 1000, [2, 1, 6]: 1010, ],
[ 'ABC': 1011, [2, 1]: 1002, [3, 4]: 1007, [2, 3]: 1012, [9, 5, 7]: 1009, ],
]
このコードは、各シーケンス内の要素が発生する順序とその内容に基づいて、複数分岐の検索ツリーを内部的に構築することによって機能します。
潜在的な注意点は、生成される ID は、各一意のシーケンスが最初に表示された順序に依存することです。これは、新しい ID はそれぞれ最後の ID よりも 1 つだけ大きいためです。
また、示されているコードではシーケンスのタイプが無視されているため、異なるコンテナーに保持されている同じ要素のシーケンスは同じ ID を生成することに注意してください。ただし、タイプを考慮して変更することもできます。