Как заменить весь тип "string" на "char" в массиве ячеек?
контекст
В R2016b MATLAB ввел новый тип данных строки в дополнение к обычному типу данных char. Пока что так хорошо, но теперь у меня много проблем с используемым ящиком JSONlab.
Например, в R2015b loadjson
возвращает массив символов ячейки 1x3:
dd = loadjson('["Titi", "Toto", "Tata"]')
dd =
'Titi' 'Toto' 'Tata'
Но в R2018a loadjson
возвращает массив строк 1x3:
dd = loadjson('["Titi", "Toto", "Tata"]')
dd =
1×3 cell array
{["Titi"]} {["Toto"]} {["Tata"]}
проблема
Чтобы не менять код везде, я хотел бы исправить процедуру loadjson
чтобы заменить все типы 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 и jsonencode для замены JSONLab в будущем, но пока я просто хочу быстро исправить ситуацию.
Ответы
Ответ 1
Вы можете использовать cellstr
(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!
cellfun
эффективности cellfun
для проверки класса:
Как в моих, так и в ответах Луиса, cellfun
используется для определения того, какие элементы являются строками. Вы можете улучшить производительность 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
[email protected]()cellfun('isclass', c, 'string');
[email protected]()cellfun(@isstring,c);
% Timing on MATLAB R2017b
timeit( f ) % >> 0.017sec
timeit( g ) % >> 0.066sec
Ответ 2
Вы можете использовать cellfun
, но он имеет более или менее ту же производительность, что и цикл:
test = {'hello', "world", 0.3; 'how', 'are', "you"};
ind = cellfun(@isstring, test);
test(ind) = cellfun(@char, test(ind), 'UniformOutput', false)
Ответ 3
На MATLAB R2017b вы можете использовать convertstringstochars:
[test{:}] = convertStringsToChars(test{:});
Ответ 4
Другое решение, обсуждаемое в блоге 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' }
Согласно сообщению в блоге, эта функция рекурсивно проходит через вход, поэтому работает даже в такой ситуации:
test = {"target1", struct('field',{123,'456',"789"})};
ft = controllib.internal.util.hString2Char(test);
{ft{2}.field}
ans =
1×3 cell array
{[123]} {'456'} {'789'}
Взгляните на сообщение в блоге для некоторых оговорок.