如何用元胞数组中的 "char" 类型替换所有 "string" 类型?

How to replace all "string" type by "char" type in a cell array?

上下文

在 R2016b 中,MATLAB 引入了我正在使用的新 string datatype, in addition to the usual char datatype. So far, so good, but it is now giving me a lot of issues with the JSONlab 工具箱。

例如,在 R2015b 中,loadjson return 是一个 1x3 单元格 字符 数组:

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

dd = 

    'Titi'    'Toto'    'Tata'

但在 R2018a 中,loadjson return 是一个 1x3 string 数组:

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

dd =

  1×3 cell array

    {["Titi"]}    {["Toto"]}    {["Tata"]}

问题

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

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

test =

  2×3 cell array

    {'hello'}    {["world"]}    {[0.3000]}
    {'how'  }    {'are'    }    {["you" ]}

我想替换所有字符串:

cellfun(@isstring, test)

ans =

  2×3 logical array

   0   1   0
   0   0   1

有什么方法可以快速完成(即无需遍历所有元素)?

PS:我知道 jsondecode and jsonencode 将来会取代 JSONLab,但到目前为止我只想快速修补一些东西。

您可以使用 cellfun,但它的性能与循环大致相同:

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

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

C = cellstr(A) converts A to a cell array of character vectors. The input array A can be a character array, a categorical array, or, starting in R2016b, a string array.

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!

cellfun class 检查的性能说明:

在我和 Luis 的回答中,cellfun 用于确定哪些元素是字符串。您可以针对此任务提高 cellfun 的性能...

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

% rapid
ind = cellfun('isclass', test, 'string');
% akin to looping
ind = cellfun(@isstring, test);

它们具有相同的输出,在一个简单的测试中我看到速度提高了 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 

从 MATLAB R2017b 开始,您可以使用 convertstringstochars:

[test{:}] = convertStringsToChars(test{:});

另一个解决方案,discussed in the UndocumentedMATLAB blog,是controllib.internal.util.hString2Char的"semi-documented"函数。这是你如何使用它:

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'   }

根据博客post,此函数通过输入递归,因此即使在这样的情况下它也能工作:

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

ans =

  1×3 cell array

    {[123]}    {'456'}    {'789'}

查看博客 post 了解一些注意事项。