我有一个MATLAB脚本,它接受我自己在远程服务器中创建的JSON,并包含一长列3x3xN
坐标,例如N=1
:
str = '[1,2,3.14],[4,5.66,7.8],[0,0,0],';
我想避免字符串拆分,是否有任何方法可以使用strread
或类似方法来读取这个3×3×N张量?
这是一个多粒子系统,N
可能很大,但我有足够的内存可以将它全部存储在内存中。
任何有关如何在JSON中格式化数组字符串的建议也是非常受欢迎的。
答案 0 :(得分:2)
您可以使用eval
功能:
str = '[1,2,3.14],[4,5.66,7.8],[0,0,0],';
result=permute(reshape(eval(['[' ,str, ']']),3,3,[]),[2 1 3])
result =
1.00000 2.00000 3.14000
4.00000 5.66000 7.80000
0.00000 0.00000 0.00000
使用eval
连接的所有元素来创建行向量。然后行矢量重新形状为3d数组。由于在MATLAB中元素按列矩阵放置,因此需要permute
数组,因此每个3 * 3矩阵都会被转换。
note1 :无需在jSON字符串中放置[]
,因此您可以使用str2num
代替eval:
result=permute(reshape(str2num(str),3,3,[]),[2 1 3])
<强>注2 强>: 如果您按列保存数据,则无需置换:
str='1 4 0 2 5.66 0 3.14 7.8 0';
result=reshape(str2num(str),3,3,[])
更新:Ander Biguri和excaza注意到与eval
和str2num
以及Rody Oldenhuis相关的速度问题关于使用sscanf
的建议我在Octave中测试了3种方法:
a=num2str(rand(1,60000));
disp('-----SSCANF---------')
tic
sscanf(a,'%f ');
toc
disp('-----STR2NUM---------')
tic
str2num(a);
toc
disp('-----STRREAD---------')
tic
strread(a,'%f ');
toc
以下是结果:
-----SSCANF---------
Elapsed time is 0.0344398 seconds.
-----STR2NUM---------
Elapsed time is 0.142491 seconds.
-----STRREAD---------
Elapsed time is 0.515257 seconds.
因此,在您的情况下使用sscanf
会更安全,更快捷:
str='1 4 0 2 5.66 0 3.14 7.8 0';
result=reshape(sscanf(str,'%f '),3,3,[])
或
str='1, 4, 0, 2, 5.66, 0, 3.14, 7.8, 0';
result=reshape(sscanf(str,'%f,'),3,3,[])
答案 1 :(得分:2)
如果您可以保证格式始终相同,我认为使用sscanf
最简单,最安全,最快:
fmt = '[%f,%f,%f],[%f,%f,%f],[%f,%f,%f],';
data = reshape(sscanf(str, fmt), 3, 3).';
根据您的其他数据(“N
”代表什么?),您可能需要调整reshape
/ transpose
。
修改强> 根据您的评论,我认为这将非常有效地解决您的问题:
% Strip unneeded concatenation characters
str(str == ',') = ' ';
str(str == ']' | str == '[') = [];
% Reshape into workable dimensions
data = permute( reshape(sscanf(str, '%f '), 3,3,[]), [2 1 3]);
正如rahnema1所述,你可以通过调整你的JSON生成器来吐出数据专栏而没有括号来避免permute
和/或字符删除,但是你必须问自己这些问题:
要记住一些事情:
现在取决于您的连接速度,我会快速真的恼怒真正因为每次小测试运行的时间大约是应该的3倍服用:)
因此,如果无法直接调用原始数据的API,我至少会在JSON中使用该数据。