数据
我目前正在处理非常大的JSON文件,格式如下
{key: [1000+ * arrays of length 241],
key2: [1000+ * arrays of length 241],
(...repeat 5-8 times...)}
数据的结构方式是每个键数组中的nth元素属于nth实体。把它想象成每个键都是一个描述符,比如“高度”或“压力”。因此,要获得实体的“高度”和“压力”,可以访问所有数组中的实体索引n。因此,所有键的数组都是相同长度的Z
正如你所能想象的,这是一种整体上的痛苦。因此,每当我执行任何数据操作时,我都会返回一个长度为Z的蒙面数组,该数组由1和0填充。1表示该索引中的每个键中的数据将被保留,0表示应该省略它)
问题
一旦执行了所有数据操作,我需要将蒙面数组应用于数据以返回原始JSON数据的副本,但其中每个键的数组Z的长度等于掩码数组中的1's数(如果在索引n处的蒙面数组中的元素为0,则索引n中的元素将从json键的所有数组中移除,反之亦然)
我的尝试
# mask: masked array
# d: data to apply the mask to
def apply_mask(mask, d):
keys = d.keys()
print(keys)
rem = [] #List of index to remove
for i in range(len(mask)):
if mask[i] == 0:
rem.append(i) #Populate 'rem'
for k in keys:
d[k] = [elem for elem in d[k] if not d[k].index(elem) in rem]
return d
这按照预期工作,但在这样大的JSON数据上需要一段时间。
问题
我希望上面的一切都是清楚的,并帮助你理解我的问题:
是否有一种更优/更快的方法将蒙面数组应用于数据,如上面所示?
干杯
发布于 2020-03-21 03:04:51
这会很慢,因为
d[k] = [elem for elem in d[k] if not d[k].index(elem) in rem]
每次都是完全重新创建内部列表。
由于您已经对d
进行了就地修改,所以只需删除相应的元素:
def apply_mask(mask, d):
for i, keep in enumerate(mask):
if not keep:
for key in d:
del d[key][i - len(mask)]
return d
(之所以使用负索引i - len(mask)
,是因为如果列表已经由于先前删除的元素而更改其长度,则正索引不再起作用。)
发布于 2020-03-21 11:48:52
这个问题来自于代码的高算法复杂性。设计一种更快的算法是可能的。
设K是字典d
中的键数。len(d)
)。让Z当面具的大小。len(mask)
),它也是d
中数组值的典型大小(即任何key
的len(d[key])
)。
初始代码的算法复杂度为O(Z^3 * K)
.。这是因为rem
是一个列表,in rem
是用线性时间完成的,也是因为d[k].index(elem)
在d[k]
中搜索elem
的时间也是线性的。
费恩福特提出的解决方案更快。实际上,他的代码的复杂性是O(Z^2 * K)
(因为del
是在CPython列表上以线性时间完成的)。
但是,可以在线性时间内进行计算:O(K * Z)
.。以下是如何:
def apply_mask(mask, d):
for key in d:
d[key] = [e for i,e in enumerate(d[key]) if mask[i]!=0]
return d
这段代码应该更快几个数量级。
PS:我认为初始算法对于问题的描述是不正确的。实际上,应该保留的一些项可以被删除,因为在迭代之间没有清除rem
(所以索引是累积的)。
https://stackoverflow.com/questions/60783816
复制相似问题