Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python数组的越界赋值-我是在重新发明轮子吗?_Python_Arrays - Fatal编程技术网

python数组的越界赋值-我是在重新发明轮子吗?

python数组的越界赋值-我是在重新发明轮子吗?,python,arrays,Python,Arrays,我需要建立一个数组,但我收到的数据顺序不正确(我不知道数组的最高索引是什么),因此我需要一种方法,在索引经常超出范围时执行array[index]=item 我很快将这个函数组合起来,实现了我想要的功能,但我觉得可能有一个更简单的方法 def oob_assign(array,index,item,default): "set array[index] to item. if index is out of bounds, array is extended as necessary usi

我需要建立一个数组,但我收到的数据顺序不正确(我不知道数组的最高索引是什么),因此我需要一种方法,在索引经常超出范围时执行
array[index]=item

我很快将这个函数组合起来,实现了我想要的功能,但我觉得可能有一个更简单的方法

def oob_assign(array,index,item,default):
  "set array[index] to item. if index is out of bounds, array is extended as necessary using default"
  array.extend([default]*(index-len(array)+1))
  array[index]=(item)
例如:

In [4]: a=[]

In [5]: oob_assign(a,5,"five",0)

In [6]: a
Out[6]: [0, 0, 0, 0, 0, 'five']

In [7]: a[5]
Out[7]: 'five'
In [1]: random_data = [(4, 'd'), (1, 'a'), (3, 'c'), (2, 'b')]
In [2]: data_items = []
In [3]: for index, data_value in random_data:
   ...:     data_items.append((index, data_value))
   ...: 
In [4]: data_items.sort()
In [5]: indices, data = zip(*data_items)
In [6]: indices
Out[6]: (1, 2, 3, 4)
In [7]: data
Out[7]: ('a', 'b', 'c', 'd')
编辑:虽然我的最终目标是在stackoverflow问题中问得有点太多,但我需要(相对较快地)对结果数据执行以下操作:

  • 按索引顺序迭代值(仅限非默认值)
  • 按索引查找值
该数据集足够小(约1000个元素),因此阵列的内存使用不会成为问题


编辑:谢谢所有的好答案!I您能否通过
附加
(索引、数据值)
存储在列表中?然后可以按索引值对列表进行排序:

data_items = []
for index, data_value in generate_out_of_order_data():
    data_items.append((index, data_value))
data_items.sort()
indices, data = zip(*data_items)
例如:

In [4]: a=[]

In [5]: oob_assign(a,5,"five",0)

In [6]: a
Out[6]: [0, 0, 0, 0, 0, 'five']

In [7]: a[5]
Out[7]: 'five'
In [1]: random_data = [(4, 'd'), (1, 'a'), (3, 'c'), (2, 'b')]
In [2]: data_items = []
In [3]: for index, data_value in random_data:
   ...:     data_items.append((index, data_value))
   ...: 
In [4]: data_items.sort()
In [5]: indices, data = zip(*data_items)
In [6]: indices
Out[6]: (1, 2, 3, 4)
In [7]: data
Out[7]: ('a', 'b', 'c', 'd')

下面是一个自我扩展列表:

class OOBList(list):
    def __init__(self, default, *args, **kwargs):
        super(OOBList, self).__init__(*args, **kwargs)
        self.default = default

    def __setitem__(self, index, value):
        max_index = len(self) - 1
        if index > max_index:
            self.extend([self.default] * (index - max_index))
        super(OOBList, self).__setitem__(index, value)
当分配给列表末尾以外的索引时,它会将列表扩展到足以容纳它的长度


由于它是列表的子类,所以显示时不需要排序(但一次重复扩展列表可能会很昂贵)。

如果您想保持这种稀疏性(即,如果在上一个最高索引为25时设置索引50,则只需要创建一个新元素,而不是25),这里最明显的答案是一个dict,加上一个“所见最大索引”int

这里有一个权衡。显然,一个真正的
列表
对于某些操作来说会更快,并且当列表实际上是密集的而不是稀疏的时,会使用更少的存储,并且会在实现复杂切片等方面帮助我们更多

但是,如果您正在考虑使用
defaultdict
,这就是您要寻找的方向。A做了许多您需要的额外工作,但它不允许您迭代这些值,也不允许您给出正确的
len
,它将创建和存储新的值,而不是让它们稀疏地存在。你可以添加这些东西……但实际上,如果你不能直接使用
defaultdict
,那就没什么帮助了;我们已经知道在哪里需要默认化,在哪里不需要默认化,而且它已经在一个包装器中,所以

要构建一个自定义的
列表
类对象,您只需定义几个方法,然后让我们为您定义其余的方法

class ExpandoList(collections.abc.MutableSequence):
    def __init__(self):
        self.d = {}
        self.maxidx = -1
    def __setitem__(self, idx, value):
        self.maxidx = max(idx, self.maxidx)
        self.d[idx] = value
    def __getitem__(self, idx):
        self.maxidx = max(idx, self.maxidx)
        return self.d.get(idx, 0)
    def __delitem__(self, idx):
        for i in range(i, self.maxidx):
            self.d[i] = self.d[i-1]
        self.maxidx -= 1
    def insert(self, idx, value):
        for i in reversed(range(i, self.maxidx)):
            self.d[i] = self.d[i-1]
        self.d[idx] = value
        self.maxidx += 1
    def __iter__(self):
        yield from (self[i] for i in range(self.maxidx))
    def __len__(self):
        return self.maxidx

注意,这不做切片。你可以手动处理,但它比我想要的答案复杂得多。如果你想进一步了解这个问题,我有一个<代码> LyyList类,我可以上载一个显示如何解决你需要解决的问题的地方。

你需要的是Python中的动态数组。动态数组是一个“List'”,你应该简单地考虑<代码>集合。这可能没有帮助的两个原因:(1)您不能迭代不存在的键,只需使用
[]
,(2)在代码调用者中,
oob\u assign
可以在每次调用中指定不同的默认值,但
defaultdict
没有这样的功能。但你永远不会知道,问题中的例子并不总是有代表性的。@stevejessop我认为defaultdict可能是适合我的情况的正确答案,但不幸的是,这只是一个评论而不是答案;)@pix,你想用你的数据做什么?您只是将其存储,然后将其写入数据库吗?是否要转换为
numpy.array
并使用
matplotlib
打印它?根据你在一个结构中获得数据后想做什么,你将决定你应该选择哪一个结构。@pix:那么我将宣布一个道义上的胜利,因为我厚颜无耻地忽略了问题中与我的答案不符的部分;-)Kirk的答案是与
defaultdict
相同主题的变体,abarnert也回答了第(1)点。这不允许您分配到切片。“我认为这是可以的,只要你指出这一点。”一个有趣的观点。我不经常这样做,也没有想过。我认为这是对同一个轮子的一次更美丽的再发明;)“我们应该在这里减少self.maxidx吗”--打开一个蠕虫罐头<代码>foo=ExpandoList();foo[0];foo[2];德福[2]
len(foo)
可能是3、2或1,尽管我不认为将其设为1会很快。@SteveJessop:反省一下,如果这应该像一个
列表一样工作,那么它必须将其他所有人推上;否则,它将是一个完全不同的数据结构。是的,这是O(N)而不是O(1),但是对于
列表
,情况也是如此,所以这不是问题。@SteveJessop:当然,OP并不一定真的想要一个列表,只是在某些方面像列表一样工作,在其他方面可能不同。因此,可能有一种更合理的设计,它更像是一个列表dict混合体(
blist
在封面下有类似的东西,作为两层中的一层,你可以放在它的树上,但不暴露它…)。不过我认为“稀疏性”和“删除性”之间的相互作用并不一定明显。也许删除最高的“真实”值也应该删除它下面的“不真实”区域,也许不是。因为提问者在评论中说,
defaultdict
将为他们做这项工作,所以你做哪一项可能无关紧要:-)@SteveJessop:我假设他希望实现简洁,但不希望接口简洁(因此,就好像所有那些0都存在,即使它们不存在)。但是你是对的,如果你想让它也成为接口的一部分,那么删除top值应该做什么是不明确的。无论如何,我怀疑这个评论只是意味着他没有考虑到其中的一些问题,并不是说他根据心理规范检查了这些问题,并且这些问题是合适的。