python中多维数组元素的唯一ID

时间:2011-12-12 22:58:52

标签: python multidimensional-array unique-id

我有一个多维数组,其元素可以完全随机。例如,

[
    [ [1, 2], [2, 1], [3, 1], [4, 2] ],
    [ [2, 1], [4, 3], [3, 4], [1, 3] ]
]

我想为每个唯一元素分配一个ID(如[1,2]中所示,而不是那些元素中的元素),以便稍后当这个数组更大时我可以识别它,但我不能似乎弄清楚了。我一直在互联网上搜索一段时间没有运气,所以如果有人能给我一个正确的方向,我真的很感激。

4 个答案:

答案 0 :(得分:2)

如何使用这样的东西?

class ItemUniqifier(object):
    def __init__(self):
        self.id = 0
        self.element_map = {}
        self.reverse_map = {}

    def getIdFor(self, obj):
        obj_id = self.element_map.get(obj)
        if obj_id is None:
            obj_id = self.id
            self.element_map[obj] = obj_id
            self.reverse_map[obj_id] = obj
            self.id += 1
        return obj_id

    def getObj(self, id):
        return self.reverse_map.get(id)

uniqifier = ItemUniqifier()
print uniqifier.getIdFor((1,2))
print uniqifier.getIdFor((1,2))
print uniqifier.getIdFor("hello")
print uniqifier.getObj(0)
print uniqifier.getObj(1)

打印:

0
0
1
(1, 2)
hello

因此,例如,要创建一个大型数组,您可以执行以下操作:

uniqifier = ItemUniqifier()
sample_array = []
for j in range(3):
    inside_array = []
    for i in range(10):
        inside_array.append(uniqifier.getIdFor((i, i+1)))
    sample_array.append(inside_array)

import pprint
pprint.pprint(sample_array)

for inside in sample_array:
    for elem in inside:
        print uniqifier.getObj(elem),
    print

打印:

[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]]
(0, 1) (1, 2) (2, 3) (3, 4) (4, 5) (5, 6) (6, 7) (7, 8) (8, 9) (9, 10)
(0, 1) (1, 2) (2, 3) (3, 4) (4, 5) (5, 6) (6, 7) (7, 8) (8, 9) (9, 10)
(0, 1) (1, 2) (2, 3) (3, 4) (4, 5) (5, 6) (6, 7) (7, 8) (8, 9) (9, 10)

答案 1 :(得分:0)

最简单的方法是使用字典,如下所示:

id_map = { 'some_id'  : example_array[0][0][0], # maps 'some_id'  to [1, 2]
           'other_id' : example_array[0][1][3], # maps 'other_id' to [3, 4]
           # add more if wanted...
         }

虽然字典 CAN 同时使用字母和数字键,但建议不要使用数字键来引用索引,因为这可能会导致与列表索引编号混淆。

此外,词典可以按需添加新密钥,如下所示:

id_map[new_key] = new_pair

由于您说动态生成了列表,因此这是最佳选择。

由于每个数字对都是通过3个索引调用访问的,也许你应该使id长3个?例如,[1, 2]会映射到ID '000'[3, 4]到ID '013'

Dictionaries - Python Documentation

答案 2 :(得分:0)

如果每个“元素”是两个单位数的基数10整数的序列,您可以从其内容为每个元素生成一个唯一的ID,如下所示:

def uniqueID(elem):
    return elem[0]*10 + elem[1]

基本思想是找出使用元素内容生成ID的一些方法。当然,具体如何完成取决于内容是什么。

答案 3 :(得分:0)

这是另一个可以处理混合类型的答案 - 即列表,元组和&字符串 - 可变长度(甚至零长度)序列。

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多一个。

另请注意,保存在不同容器中的相同元素的序列将生成相同的ID,因为在显示的代码中忽略了序列类型 - 但也可以将其更改为考虑类型。