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问题中问得有点太多,但我需要(相对较快地)对结果数据执行以下操作:
- 按索引顺序迭代值(仅限非默认值)
- 按索引查找值
编辑:谢谢所有的好答案!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值应该做什么是不明确的。无论如何,我怀疑这个评论只是意味着他没有考虑到其中的一些问题,并不是说他根据心理规范检查了这些问题,并且这些问题是合适的。