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

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

Accepted Answer

Atsushi Ueno
Atsushi Ueno on 24 Sep 2021
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
早急なご回答誠にありがとうございます.
参考にし書き換え使用させていただきたいとおもいます.
もしよろしければ追加で下記教えていただきたく思います
cellfun(@(x) x(4:end),C,'uni',false)
の@は関数の前に置くルールだとヘルプを読み,そのように理解いたしまいした
(x),とはどのような意味合いなのでしょうか
またその後におく’uni'とは何を表しているでしょうか
恐れ入りますがご教示いただけると幸いです.
  4 Comments
浩祐 佐々木
浩祐 佐々木 on 27 Sep 2021
すいません,追記させてください
上記,色々書きましたが
やりたいことは
abcdef_ghi_0_
abcdef_ghi1
abcdef_ghi2
などがあった時にこれらは本質的には
abcdef_ghi
と同じデータなので
大元のデータベースのデータ群からabcdef_ghiを参照しに行って欲しいのです.
ですので「部分一致(?)のように最も整合している文字列」を検索してそれに該当する名前を
大元データベースから提示しれくれるよなことをしたいと考えておるのですが
それを簡便に記述できず...
Atsushi Ueno
Atsushi Ueno on 27 Sep 2021
単純なルールに対しては単純な処理が良いですが、ルールが複雑になってくると@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

Find more on 文字と文字列 in Help Center and File Exchange

Products

Community Treasure Hunt

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

Start Hunting!