如何有效地将3x3xN坐标字符串读入matlab数组

时间:2016-11-21 06:17:39

标签: json matlab

我有一个MATLAB脚本,它接受我自己在远程服务器中创建的JSON,并包含一长列3x3xN坐标,例如N=1

str = '[1,2,3.14],[4,5.66,7.8],[0,0,0],';

我想避免字符串拆分,是否有任何方法可以使用strread或类似方法来读取这个3×3×N张量?

这是一个多粒子系统,N可能很大,但我有足够的内存可以将它全部存储在内存中。

任何有关如何在JSON中格式化数组字符串的建议也是非常受欢迎的。

2 个答案:

答案 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 Biguriexcaza注意到与evalstr2num以及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和/或字符删除,但是你必须问自己这些问题:

  1. 这是否真的值得付出努力,考虑到这里的代码已经非常小而且效率很高
  2. 其他应用程序是否将使用JSON接口,因为从本质上讲,您只是为了适应您的处理脚本而对JSON输出进行去泛化。我认为这是一个非常糟糕的设计实践,但是哦。
  3. 要记住一些事情:

    • 以二进制形式发出500k值约为34 MB
    • 在ASCII中执行相同的操作大约是110 MB

    现在取决于您的连接速度,我会快速真的恼怒真正因为每次小测试运行的时间大约是应该的3倍服用:)

    因此,如果无法直接调用原始数据的API,我至少会在JSON中使用该数据。