JSZ
JSZ

Reputation: 227

Matlab referencing of part of string in cell array

I'm looking for a way to reference parts of strings that are stored in a cell array. I need to do so in order to make a logical statement that will match strings I am looking for to the parts of the strings in the cell array.

Lets say my cell array looks like this:

cellname = { 'B_1J_1234_1236' , 'A_1W_2345_2349' , 'C_2J_9876_9879' , 'B_1W_5432_5438'}

And I am looking to find the string in the cell array that satisfies:

  1. 'B' as the first part of the string
  2. '1W' as the second part of the string
  3. The first number (third part) is less than 5434
  4. The second number (fourth part) is greater than 5436

I know I can get an index of the element I am looking for that satisfies my first two search conditions by writing:

find(strncmp(cellname,'B_1W',4))

But I cannot find a way to include the latter conditions. Any ideas?

EDIT: Ideally, I guess I'd like someway to do:

find(strncmp(cellname,'B_1W',4) & cellname{ "any element" } (6:9) < 5434 & cellname{ "any element" } (11:14) > 5436)

But it is the referencing of a part of "any element" that I can't figure out how to do.

Upvotes: 2

Views: 170

Answers (3)

Luis Mendo
Luis Mendo

Reputation: 112659

Using regular expressions:

cellfun(@(x) ~isempty(x) && str2num(x.m)<5434 && str2num(x.n)>5436, ...
    regexp(cellname, '^B_1W_(?<m>\d+)_(?<n>\d+)', 'names'))

Upvotes: 0

Matt
Matt

Reputation: 13923

You can solve this problem by using cellfun and a self-defined function. In this function you can split the string in substrings using strsplit with the delimiter _. Then simply check if all conditions are met which returns true or false accordingly. Note that we need to convert the string in the third and fourth field to a number. This can be done with str2double.

function main
    cellname = { 'B_1J_1234_1236' , ...
                 'A_1W_2345_2349' , ...
                 'C_2J_9876_9879' , ...
                 'B_1W_5432_5438' };

    R = cellfun(@check, cellname, 'UniformOutput',1)
    find(R==true)
end


function out = check(in)
    S = strsplit(in,'_');
    out = strcmp(S{1},'B') && strcmp(S{2},'1W') && ...
          str2double(S{3})<5434 && str2double(S{4})>5436
end

This is the output:

R =
     0     0     0     1
ans =
     4

In case you want to use something similar to what you proposed, you can use cellfun as well:

find(strncmp(cellname,'B_1W',4) & ...
         cellfun(@(x)str2double(x(6:9))<5434,cellname) & ...
         cellfun(@(x)str2double(x(11:14))>5436,cellname))

Upvotes: 3

user1543042
user1543042

Reputation: 3440

Very similar to Matt's but in one line

cellfun(@(x) strcmp(x{1}, 'B') && strcmp(x{2}, '1W') && (str2num(x{3}) < 5434) && (str2num(x{4}) > 5436), cellfun(@(x) strsplit(x, '_'), cellname(:)', 'uni', 0))

Upvotes: 2

Related Questions