Find strings that contain multiple substrings at the same time
25 ビュー (過去 30 日間)
古いコメントを表示
Hi, I have a array of strings and I would like to identify all those entries that contain two substrings at the same time. For example:
My strings are: 'First Example','Second Example', 'Third Example'
My Substrings are: 'irs','xam'
So I would like to identify the first string as the only one which contains both substrings. I have found a solution, but I am convinced that there must be a more elegant and efficient way of achieving this. My code looks as follows:
clear;clc;
%set variables
rbCode = {'RB_DEP_LI_EQ_EED'; ...
'RB_DEP_LI_EQ_EED_INV'; ...
'RB_DEP_LI_EQ_EED_TRS'; ...
'RB_DEP_LI_EQ_IED'
'RB_DEP_LI_EQ_IED_INV'; ...
'RB_DEP_LI_EQ_IED_TRS'; ...
'RB_DEP_LI_FI_INV'};
rbMarketValue = {100; 80; 20; 70; 40; 30; 20};
%compare invested market value
strToFind ={'EQ';'_INV'};
%sum up rbMarketValue for all rbCodes that have both 'EQ' and '_INV' in
%their name
a = arrayfun(@(x) strfind(rbCode,char(strToFind(x))),1:size(strToFind),'un',false);
a1 = arrayfun(@(x) logical(~isempty(cell2mat(a{1,1}(x,1)))),1:size(rbCode));
a2 = arrayfun(@(x) logical(~isempty(cell2mat(a{1,2}(x,1)))),1:size(rbCode));
a3 = sum([a1' a2'],2);
a4 = cell2mat(rbMarketValue);
sumDeptInv = sum(a4(a3==2));
Any suggestion how I can achieve this? Thanks Sven
2 件のコメント
dpb
2015 年 4 月 8 日
regular expressions (but I'm such a feeb I'll leave the actual expression to someone who can write it w/o having to read the full text... :) )
Stephen23
2015 年 4 月 8 日
Is the order of the substrings known and fixed? If they have a fixed order, then this could be solved using a simple regular expression. If the order is not known, as your code currently solves, then this requires either two parses of the strings or some kind of pre-processing.
採用された回答
Stephen23
2015 年 4 月 8 日
編集済み: Stephen23
2015 年 4 月 9 日
Actually using strfind is often faster than using regexp, and it has the significant advantage that all characters are interpreted literally (and not as special characters like with regexp). strfind can be used quite compactly for your task:
rbCode = {'RB_DEP_LI_EQ_EED'; ...
'RB_DEP_LI_EQ_EED_INV'; ...
'RB_DEP_LI_EQ_EED_TRS'; ...
'RB_DEP_LI_EQ_IED'
'RB_DEP_LI_EQ_IED_INV'; ...
'RB_DEP_LI_EQ_IED_TRS'; ...
'RB_DEP_LI_FI_INV'};
strToFind ={'EQ';'_INV'};
>> fun = @(s)~cellfun('isempty',strfind(rbCode,s))
>> out = cellfun(fun,strToFind,'UniformOutput',false)
>> idx = all(horzcat(out{:}),2)
idx =
0
1
0
0
1
0
0
2 件のコメント
Jos (10584)
2015 年 4 月 9 日
編集済み: Jos (10584)
2015 年 4 月 9 日
Here is a REGEXP way of solving this (but I also prefer the strained solution posted by Stephen!)
tf = cellfun(@(x) numel(x)==2,regexp(rbCode,sprintf('%s|',strToFind{:})))
その他の回答 (1 件)
Sven
2015 年 4 月 8 日
編集済み: Sven
2015 年 4 月 8 日
Hi Sven,
Here's how I would do it. It uses a call to regexp (you could also use strsplit) and one cellfun. The good thing about building a lookup table is that if your data is very large, there will only be an initial "hit" in terms of string comparison processing to build the lookup table, and after that you will be dealing with logical masks so any subsequent questions you ask (say, if you chose a different pair of codes) will be very efficient:
% Set up your problem
rbCode = {'RB_DEP_LI_EQ_EED'; ...
'RB_DEP_LI_EQ_EED_INV'; ...
'RB_DEP_LI_EQ_EED_TRS'; ...
'RB_DEP_LI_EQ_IED'
'RB_DEP_LI_EQ_IED_INV'; ...
'RB_DEP_LI_EQ_IED_TRS'; ...
'RB_DEP_LI_FI_INV'};
rbMarketValues = [100; 80; 20; 70; 40; 30; 20];
strToFind ={'EQ';'INV'};
% Find all codes and build a lookup table showing which are present
rbToks = regexp(rbCode,'_','split');
codes = unique([rbToks{:}]); % You won't need this if you already have a list
codeLookup = cell2mat(cellfun(@(tok)ismember(codes,tok),rbToks,'Un',0));
% Look in your lookup to see which entries have both codes
hasBothMask = all(codeLookup(:,ismember(codes,strToFind)),2);
sumDeptInv = sum(rbMarketValues(hasBothMask))
Did that make sense?
Thanks,
Sven.
参考
カテゴリ
Help Center および File Exchange で Characters and Strings についてさらに検索
製品
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!