web-dev-qa-db-ja.com

セル配列内のすべての「string」タイプを「char」タイプに置き換える方法は?

環境

R2016bでは、MATLABは通常の char データ型に加えて、新しい string データ型を導入しました。これまでのところ、とても良いですが、今使っている JSONlab ツールボックスに多くの問題が生じています。

たとえば、R2015bでは、loadjsonは1x3セルcharacter配列を返します。

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

dd = 

    'Titi'    'Toto'    'Tata'

しかし、R2018aでは、loadjsonは1x3string配列を返します。

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:私は jsondecodejsonencode を将来的にJSONLabに置き換えることを知っていますが、これまでのところ、パッチをすばやく適用したいと思っています。

25
CitizenInsane

cellstr(混乱しますが、 "str"がstringを示唆しているにもかかわらず)ループを行わずに文字列を文字配列に変換したり、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!

A cellfunクラスチェックのパフォーマンスノート:

私の回答とLuisの回答の両方で、cellfunを使用して、どの要素が文字列であるかを判断します。このタスクのcellfunのパフォーマンスを改善できます...

cellfun docsによると、対応する関数ハンドルよりもはるかに高速な文字配列オプションがいくつかあります。 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 
17
Wolfie

MATLAB R2017b以降は convertstringstochars を使用できます:

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

cellfunを使用できますが、パフォーマンスはループとほぼ同じです。

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

別の解決策 ndocumentedMATLABブログで説明 は、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'}

いくつかの警告については、ブログ投稿をご覧ください。

8
Dev-iL