How can I find multiple strings in a cell array?

66 visualizaciones (últimos 30 días)
Paul Fishback
Paul Fishback el 6 de Abr. de 2016
Comentada: Dooyoung Kim el 2 de Ag. de 2018
I have a cell array of strings, called Channels, each containing an EEG channel label, e.g. 'A1', 'A2', ....,
I'd like to find indices that correspond to a subset of the strings. For a single string, I've found the following works:
Match=cellfun(@(x) strcmp({'A3'}, x), Channels, 'UniformOutput', 0);r=find(cell2mat(Match))
The value of r is 3, which is what I would expect. However, if I try to find indices that match more than one channel, I obtain an answer I cannot interpret. For example,
Match=cellfun(@(x) strcmp({'A1','A2','A3'}, x), Channels, 'UniformOutput', 0);r=find(cell2mat(Match))
r=1, 5, 9, which is incorrect. The values should be 1, 2, 3.

Respuesta aceptada

Adam
Adam el 6 de Abr. de 2016
Try:
Match=cellfun(@(x) ismember(x, {'A1','A2','A3'}), Channels, 'UniformOutput', 0);
r=find(cell2mat(Match));
  2 comentarios
Paul Fishback
Paul Fishback el 6 de Abr. de 2016
Thanks! Works perfectly.
Guillaume
Guillaume el 6 de Abr. de 2016
And unnecessarily complicated...

Iniciar sesión para comentar.

Más respuestas (1)

Guillaume
Guillaume el 6 de Abr. de 2016
Editada: Guillaume el 6 de Abr. de 2016
First, your first solution is unnecessarily complicated. You're basically using a loop ( cellfun) to compare each individual string with 'A3'. When you're comparing individual strings with each others, strcmp returns a scalar, so you don't need to have 'UniformOutput', false in your cellfun call. As a result, your Match would be a matrix and you wouldn't need the subsequent cell2mat either. But in any case, you don't even need the loop since strcmp is happy to directly compare a string with a cell array. So your first example could simply be:
r = find(strcmp('A3', Channels))
Now, in your second case, if you still were to use strcmp for the comparison, you would indeed need cellfun (or an explicit loop) to break your Channels cell array into individual strings as you can't strcmp two cell arrays together (expect if they're the same size but then it's a different behaviour). When you do
strcmp({'A1', 'A2', 'A3'}, x)
the output is a vector with 3 elements of either 0s or 1s, telling you respectively whether 'A1', 'A2', 'A3' matches x. So for example if x is 'A2', you get as output [0 1 0]. Therefore assuming your Channels is the {'A1'; 'A2'; 'A3'}, the output of your cellfun is:
{[1 0 0]; %first string of {'A1', 'A2', 'A3'} matches x (first string of Channels)
[0 1 0]; %second string of {'A1', 'A2', 'A3'} matches x (second string of Channels)
[0 0 1]} %third string of {'A1', 'A2', 'A3'} matches x (third string of Channels)
The cell2mat call then convert that into a matrix that happens to be the identity matrix, and find on that indeed returns [1, 5, 9].
The problem with the above is that you don't want a vector for each x, you just want one value that tells you whether or not any of 'A1', 'A2', 'A3' matches x. So you could change the cellfun to:
Match = cellfun(@(x) any(strcmp({'A1', 'A2', 'A3'}, x, Channels); r = find(Match);
Note that again you don't need the 'UniformOutput', false and the cell2mat call since the output of cellfun is now scalar.
However, what you're now doing is testing the membership of one set into another. There is a function for that in matlab: ismember. So the simplest way to do your second comparison is simply with:
r = find(ismember(Channels, {'A1', 'A2', 'A3'}))
  3 comentarios
Adam
Adam el 6 de Abr. de 2016
Yes, that is true. I didn't look too closely at the details, I just substituted your strcmp for an ismember, tested it and left everything else as it was!
Dooyoung Kim
Dooyoung Kim el 2 de Ag. de 2018
Thanks. It's simple and works well!

Iniciar sesión para comentar.

Categorías

Más información sobre Data Type Conversion en Help Center y File Exchange.

Community Treasure Hunt

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

Start Hunting!

Translated by