如何在单元格数组中用"char"类型替换所有"字符串"类型?

Cit*_*ane 25 arrays string matlab type-conversion cell-array

上下文

在R2016b中,除了通常的char数据类型之外,MATLAB还引入了一种新的字符串数据类型.到目前为止,这么好,但它现在给了我很多我正在使用的JSONlab工具箱的问题.

例如,在R2015b中,loadjson返回1x3单元字符数组:

dd = loadjson('["Titi", "Toto", "Tata"]')

dd = 

    'Titi'    'Toto'    'Tata'
Run Code Online (Sandbox Code Playgroud)

但是在R2018a中,loadjson返回1x3 字符串数组:

dd = loadjson('["Titi", "Toto", "Tata"]')

dd =

  1×3 cell array

    {["Titi"]}    {["Toto"]}    {["Tata"]}
Run Code Online (Sandbox Code Playgroud)

问题

为了不必在任何地方更改我的代码,我想修补loadjson例程以替换string它可能返回char类型的所有类型.例如,在以下单元格数组中:

test = { 'hello', "world", 0.3; 'how', 'are', "you"}

test =

  2×3 cell array

    {'hello'}    {["world"]}    {[0.3000]}
    {'how'  }    {'are'    }    {["you" ]}
Run Code Online (Sandbox Code Playgroud)

我想替换所有字符串:

cellfun(@isstring, test)

ans =

  2×3 logical array

   0   1   0
   0   0   1
Run Code Online (Sandbox Code Playgroud)

有没有办法可以快速完成(即没有循环遍历所有元素)?

PS:我知道jsondecodejsonencode将来取代JSONLab,但到目前为止我只是想快速修补一些东西.

Wol*_*fie 17

您可以使用cellstr(令人困惑的,尽管"str"建议字符串)将字符串转换为字符数组而不循环或cellfun...文档声明如下:

C = cellstr(A)转换A为字符向量的单元格数组.输入数组A可以是字符数组,分类数组,或者从R2016b开始,是字符串数组.

test = {'hello', "world", 0.3; 'how', 'are', "you"}; % multi-type test cell array
ind = cellfun(@isstring, test);                      % indexing for string type items
test(ind) = cellstr(test(ind))                       % char-ify the strings!
Run Code Online (Sandbox Code Playgroud)

cellfun类检查性能注意:

在我和路易斯的答案中,cellfun用于确定哪些元素是字符串.您可以改善cellfun此任务的性能......

根据cellfun文档,有一些字符数组选项比它们的函数句柄对应程序快得多.对于isstring索引,运行第一个索引可能要快得多:

% rapid
ind = cellfun('isclass', test, 'string');
% akin to looping
ind = cellfun(@isstring, test);
Run Code Online (Sandbox Code Playgroud)

它们具有相同的输出,在一个简单的测试中我看到了4倍的速度改进:

% Create large test array of random strings
c = cell(100,1000);
c = cellfun(@(x) string(char(randi([65,122],1,10))), c, 'uni', 0);

% Create functions for benchmarking 
f=@()cellfun('isclass', c, 'string');
g=@()cellfun(@isstring,c);

% Timing on MATLAB R2017b
timeit( f ) % >> 0.017sec
timeit( g ) % >> 0.066sec 
Run Code Online (Sandbox Code Playgroud)


Lui*_*ndo 11

您可以使用cellfun,但它与循环具有或多或少相同的性能:

test = {'hello', "world", 0.3; 'how', 'are', "you"};
ind = cellfun(@isstring, test);
test(ind) = cellfun(@char, test(ind), 'UniformOutput', false)
Run Code Online (Sandbox Code Playgroud)


rah*_*ma1 11

作为MATLAB R2017b您可以使用convertstringstochars:

[test{:}] = convertStringsToChars(test{:});
Run Code Online (Sandbox Code Playgroud)


Dev*_*-iL 8

在UndocumentedMATLAB博客中讨论的另一个解决方案是"半文档化"功能controllib.internal.util.hString2Char.这是你如何使用它:

test = { 'hello', "world", 0.3; 'how', 'are', "you"};
fixed_test = controllib.internal.util.hString2Char(test);

fixed_test =

  2×3 cell array

    {'hello'}    {'world'}    {[0.3000]}
    {'how'  }    {'are'  }    {'you'   }
Run Code Online (Sandbox Code Playgroud)

根据博客文章,这个函数通过输入递归,所以它甚至在这样的情况下工作:

test = {"target1", struct('field',{123,'456',"789"})};
ft = controllib.internal.util.hString2Char(test);
{ft{2}.field}

ans =

  1×3 cell array

    {[123]}    {'456'}    {'789'}
Run Code Online (Sandbox Code Playgroud)

请看一下博客文章中的一些警告.