如何用元胞数组中的 "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 了解一些注意事项。
上下文
在 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)
convertsA
to a cell array of character vectors. The input arrayA
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 了解一些注意事项。