这是另一个可以处理可变长度(甚至零长度)序列的混合类型(即列表、元组和字符串)的答案。
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,因为在显示的代码中忽略了序列的类型 - 但也可以更改它以考虑类型。