如何在插入新元素时跟踪列表索引?

时间:2012-06-26 03:30:07

标签: python list insert indexing

我有一个大清单,如下:

['a', 'b', 'c', 'd', 'e', 'f', 'g', ...]

我想用字典来跟踪它的索引。 dict看起来像这样:

{1:'a', 2:'b', 3:'c', 4:'d', 5:'e', 6:'f', 7:'g', ...}

但是我需要插入新元素。我希望插入点后列表元素的索引在插入时自动增加1。有快速或传统的方法吗?我通常使用python,但其他形式的算法也没问题。

更新:请不要无缘无故地拒绝这个问题。我认为即使省略了一些上下文(为简单起见),问题本身也相当清楚。我认为可以提供答案,而不必知道为什么我需要这样做。

3 个答案:

答案 0 :(得分:6)

为什么将dict映射到值?这就是列表已经做的事情:

>>> x = ['a', 'b', 'c', 'd', 'e', 'f', 'g', ...]
>>> x[0]
'a'
>>> x[4]
'e'

如果修改列表,例如通过插入新值,索引会自动正确。

你的dict和列表本身之间的唯一区别是列表是0索引的,你的dict是1​​索引的('a'是1)。

答案 1 :(得分:0)

您声明要使用索引来跟踪到其他列表的映射。这是一个很大的数据集,所以大概查找速度很重要(字典在这里有很大的优势)。

如果索引不是数据的绝对必要部分 - 并且只是引用关系的便捷方式 - 那么为什么要将东西存储在单独的列表中?您是否考虑过嵌套字典,以便将所有相关数据保存在一起?例如,

dataset = { 'a': { 'name':'Alice' , 'food':'pie' } , 'b': { 'name':'Bob' , 'food':'cake' , 'friend':'Eve' } }

>>> dataset['a']['food']
'pie'

这更具可读性,并且字典为给定的任意数据对大型列表提供了更快的查找速度。但是,如果不了解您的目标,很难推荐量身定制的解决方案。例如,知道是否可以通过键引用所有数据(您总是在寻找'a'),或者您是否有时想要找到特定值(每个喜欢派的人)都会有所帮助。

答案 2 :(得分:0)

这是一个封装整数重编号和基于1的索引的类。最后看一下这个类的实例如何模拟dict接口的例子,即使它本身不是一个字典。

# define DEFAULT value that is very unlikely to be a list value
DEFAULT=object()

class IndexedList(object):
    def __init__(self, seq=None):
        self._seq = list(seq) if seq is not None else []
    def __contains__(self, key):
        if isinstance(key, int):
            return 1 <= key <= len(self._seq)
        else:
            return key in self._seq
    def __getitem__(self, index):
        return self._seq[index-1]
    def __setitem__(self, index, value):
        self._seq[index-1] = value
    def __str__(self):
        return str(self._seq)
        # or if you'd rather have it look like a dict
        # return "{%s}" % ', '.join("%d: '%s'" % (i,s) for i,s in self.iteritems())
    def iterkeys(self):
        i = 1
        while i <= len(self._seq):
            yield i
            i += 1
    def keys(self):
        return list(self.iterkeys())
    def itervalues(self):
        return iter(self._seq)
    def values(self):
        return list(self.itervalues())
    def iteritems(self):
        return enumerate(self._seq, start=1)
    def items(self):
        return list(self.iteritems())
    def insert(self, i, value):
        self._seq.insert(i-1, value)
    def pop(self, i, default=DEFAULT):
        if i in self:
            return self._seq.pop(i-1)
        else:
            if default is not DEFAULT:
                return default
            else:
                raise KeyError("%s not a valid key" % i)
    # everything else, just delegate to owned list object
    def __getattr__(self, attr):
        return getattr(self._seq, attr)


# make an instance of IndexedList; print items just like it was a dict
il = IndexedList("abcdefg")
print il
print il.items()
# Prints
# ['a', 'b', 'c', 'd', 'e', 'f', 'g']
# [(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e'), (6, 'f'), (7, 'g')]
#   or if you choose to show dict-ish output
# {1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e', 6: 'f', 7: 'g'}
# [(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e'), (6, 'f'), (7, 'g')]


# insert an item into the middle of the sequence, note that
# remaining items get incremented keys
il.insert(4,'x')
print il
print il.items()
# Prints
# ['a', 'b', 'c', 'x', 'd', 'e', 'f', 'g']
# [(1, 'a'), (2, 'b'), (3, 'c'), (4, 'x'), (5, 'd'), (6, 'e'), (7, 'f'), (8, 'g')]


# test dict.pop
print il.pop(3)
print il
print il.items()
# Prints
# c
# ['a', 'b', 'x', 'd', 'e', 'f', 'g']
# [(1, 'a'), (2, 'b'), (3, 'x'), (4, 'd'), (5, 'e'), (6, 'f'), (7, 'g')]


# test 'key in dict' behavior
print 0 in il
print 3 in il
print 100 in il
print il.keys()
print il.values()
# Prints
# False
# True
# False
# [1, 2, 3, 4, 5, 6, 7]
# ['a', 'b', 'x', 'd', 'e', 'f', 'g']


# so you can treat il directly as a dict, but if you really really need a dict
# object, make one using il.iteritems
ildict = dict(il.iteritems())
print ildict
# Prints
# {1: 'a', 2: 'b', 3: 'x', 4: 'd', 5: 'e', 6: 'f', 7: 'g'}