文字ベクトルのセル配​列から文字の一部だけ​きりとり新たなセル配​列を作る方法を教えて​ください

例えば下記のような文字列ベクトルのセル配列があるとします
C = {'abcdefg1';'abcdefg2';'abcdefg3';'abcdefg4';'abcdefg5'}
この各行に入っている文字列から次のようなルールで文字列を引き抜き新たなセル配列Dを作る際はどのように書けばよいでしょうか
ルール
先頭3文字を抜く
D = {'defg1';cdefg2';'defg3';'defg4';'defg5'}
大量の手持ちのデータのラベルから新たなデータラベルを作りたいのですが
上記のようなことを記載できず困っております.
ベーシックなことで恐縮ですが教えていただけますと幸いです.

 Accepted Answer

Atsushi Ueno
Atsushi Ueno on 24 Sep 2021

2 votes

Cの内容は少し改造しました
C = {'abcdefg1';'bcdefg2';'acdefg3';'defg4';'efg5';'fg6';'g7'}
C = 7×1 cell array
{'abcdefg1'} {'bcdefg2' } {'acdefg3' } {'defg4' } {'efg5' } {'fg6' } {'g7' }
D = cellfun(@(x) x(4:end),C,'uni',false)
D = 7×1 cell array
{'defg1' } {'efg2' } {'efg3' } {'g4' } {'5' } {1×0 char} {1×0 char}

2 Comments

Akira Agata
Akira Agata on 26 Sep 2021
+1
別の方法として、正規表現を使う手もあります(ただし対象の文字列が3文字以下の場合はうまくいかないので注意が必要ですが)。
D = regexprep(C,'^\w{3}','');
R2020b以降であれば、以下でも可能です。
pat = lineBoundary('start')+alphanumericsPattern(3);
D = erase(C,pat);
Atsushi Ueno
Atsushi Ueno on 26 Sep 2021
Edited: Atsushi Ueno on 26 Sep 2021
どちらも対象の文字数を1~3文字にすればうまくいきますよ。
D = regexprep(C,'^\w{1,3}','');
pat = lineBoundary('start')+alphanumericsPattern(1,3);
F = erase(C,pat)
MATLABのpetternは可読性が高くて良いですね。
(追記)ルール(要件)が「先頭3文字を抜く」だから、先頭が1文字または2文字しかない場合にその1文字または2文字を抜いてはならないかもしれませんね。その意味では上記コメントの方が良さそうですね。
C = {'abcdefg1';'bcdefg2';'acdefg3';'defg4';'efg5';'fg6';'g7'};
D = regexprep(C,'^\w{3}','')
D = 7×1 cell array
{'defg1' } {'efg2' } {'efg3' } {'g4' } {'5' } {0×0 char} {'g7' }
pat = lineBoundary('start')+alphanumericsPattern(3);
F = erase(C,pat)
F = 7×1 cell array
{'defg1' } {'efg2' } {'efg3' } {'g4' } {'5' } {0×0 char} {'g7' }

Sign in to comment.

More Answers (1)

浩祐 佐々木
浩祐 佐々木 on 24 Sep 2021

0 votes

早急なご回答誠にありがとうございます.
参考にし書き換え使用させていただきたいとおもいます.
もしよろしければ追加で下記教えていただきたく思います
cellfun(@(x) x(4:end),C,'uni',false)
の@は関数の前に置くルールだとヘルプを読み,そのように理解いたしまいした
(x),とはどのような意味合いなのでしょうか
またその後におく’uni'とは何を表しているでしょうか
恐れ入りますがご教示いただけると幸いです.

4 Comments

Atsushi Ueno
Atsushi Ueno on 24 Sep 2021
上記の「cell 配列または string 配列内の文字に関数を適用」(リンク貼ってあります)が丁度良い例ですね。
cellfunは、セル配列の要素を1個ずつ任意の関数に入力し、出力する処理を1関数で実行できる代物です。
for i=1:numel(mycell) % 例えば今回の場合はこんな感じ
result{i} = something_func(mycell{i});
end
@は関数の前に置くルールだとヘルプを読み,そのように理解いたしました
⇒はい。因みに@(x)は無名関数で、スペース一つ空けたすぐ後に中身を書きます。普通の名前付関数を指定する場合は@mean(x)や@sum(x)のような形になります
(x),とはどのような意味合いなのでしょうか
⇒@(x)は無名関数の引数です。その後のx(4:end)を記述する為に、セル配列の要素を仲介する変数が必要なのです。
またその後におく’uni'とは何を表しているでしょうか
'uni'とその後のfalse(,'uni',false))を2組セットで設定しています。'uni'は'UniformOutput'の略です。'uni'でも指定可能です。デフォルト値はtrue(1)です。
例えばセル内の数値の合計値や平均値(スカラー)を返す場合はデフォルトのまま何も指定しなくてもOKです。今回のように出力もcell配列の場合はこの'UniformOutput'=false(0)に設定する必要があります。
浩祐 佐々木
浩祐 佐々木 on 27 Sep 2021
ご返信が遅くなり申し訳ありません.
大変勉強になりました.ご丁寧にありがとうございました.またご説明いただいたこととヘルプ併せて読むともっと理解が進みそうな気がいたします.
ちなみに,上記教示いただいたことで問題の半分程度は改善したのですが,もう一歩,といったところで下記に状況を追記させていただきます.アドバイスをいただけますと幸いです.
1.先頭4文字を抜くということで一般的なデータラベル名を引き抜くことができた
2.しかし上記4文字引き抜いたラベル名に若干余計なものが末尾に残っているものがある
3.しかし末尾に余計なものが残るものと残らない者があり残る場合もそれに規則j正がない(e.g.後ろから何番目の文字列から最後までを除けばよい,などはできない)
4.しかしながら抜きたい文字は下記のようなパターン
例1.
abcdef_ghi_0_
例2
abcdef_ghi0
例3
abcdef_ghi[0]
このような感じです
末尾に大部分は直接数字か"_"を居れて数字,のような形になっており
これらは別のものではなく同じ文字列"abcdef_ghi”としたいのですが...
ちなみに使用Matlab versionは2015,2018です.
アドバイスいただけると幸いです.
浩祐 佐々木
浩祐 佐々木 on 27 Sep 2021
すいません,追記させてください
上記,色々書きましたが
やりたいことは
abcdef_ghi_0_
abcdef_ghi1
abcdef_ghi2
などがあった時にこれらは本質的には
abcdef_ghi
と同じデータなので
大元のデータベースのデータ群からabcdef_ghiを参照しに行って欲しいのです.
ですので「部分一致(?)のように最も整合している文字列」を検索してそれに該当する名前を
大元データベースから提示しれくれるよなことをしたいと考えておるのですが
それを簡便に記述できず...
単純なルールに対しては単純な処理が良いですが、ルールが複雑になってくると@Akira Agataさんの仰る正規表現(最近のMATLABではpettern)の出番です。
大事なのは質問文の冒頭にも出てくる「ルール」を正確に見極める事です。
例えば自分の回答は「先頭3文字を抜く」という要件に対し、確認せずに先頭1~2文字しか無い場合も抜いてしまいました。もしこれが稀に見る事象に合わない場合、不具合を引き起こす時限爆弾になります。
今の例を見る限りのルールを決め、正規表現で必要なキーワードを抜き出してみます
  • 先頭4文字は除く(文字数は固定、短い文字列は絶対に現れない想定)
  • キーワードの文字種類(a~z)と文字数(6文字_3文字)で特定可能(違うかも)
  • キーワードの末尾に数字を含む不規則な文字記号が付くので除きたい
検索パターン「^.{4}([a-z]{3,6}_[a-z]{3})
^   ⇒入力文字列の先頭にマッチする(先頭から始まるパターンにしかマッチしない)
.{4} .は任意の文字、{4}は量指定子(4個ピッタリにマッチする)
(...) ⇒()内をキャプチャする。因みに括弧文字にマッチするのは\(や\)
[a-z]{6} [a-z]a~z1文字、{6}は量指定子(6個ピッタリにマッチする)
_   ⇒これはアンダースコア自体にマッチ。記号によってはエスケープが必要なので注意
G = {'ABCDabcdef_ghi_0_','1234abcdef_ghi0','+*=~abcdef_ghi[0]',...
'M7g3abcdef_ghi_0_','NE#0abcdef_ghi','****abcdef_ghi2'};
H = regexp(G,'^.{4}([a-z]{6}_[a-z]{3})','tokens'); %因みに、先頭4文字を先読みでマッチから外し'match'で結果を得る方法もあります
cellfun(@(x) x{1}{1}, H, 'uni', false) % 結果を表示
ans = 1×6 cell array
{'abcdef_ghi'} {'abcdef_ghi'} {'abcdef_ghi'} {'abcdef_ghi'} {'abcdef_ghi'} {'abcdef_ghi'}

Sign in to comment.

Categories

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!