MATLAB cellfun() to map contains() to cell array - arrays

a={'hello','world','friends'};
I want to see if for every word in the cell array contains the letter 'o', how to use cellfun() to achieve the following in a compact expression?
b = [ contains(a(1),'o') contains(a(2),'o') contains(a(3),'o')]

You don't need cellfun, if you read the documentation, contains works natively on cell arrays of characters:
a = {'hello', 'world', 'friends'};
b = contains(a, 'o');
Which returns:
b =
1×3 logical array
1 1 0

Related

Using matrix operations instead of FOR loop for boolean comparison of cell array to index value

I have a function that takes one vector as its input, uses another function to create a derivative vector from the input, and then compares the two vectors to produce its output vector. I currently have it working with a for loop as follows:
The original array, nameVec, is used as the input to the following functions:
% INPUT: nameVec = '' 'a' 'b' 'aa' 'ab' 'ba' 'aba' 'abb'
First, a function called computeParentName removes the last character from each array element of nameVec and produces this cell array:
% OUTPUT: parentNameVec = '' '' '' 'a' 'a' 'b' 'ab' 'ab
Next, the function computeParentIndex finds the indices of where each element in parentNameVec appears in nameVec:
function [parentIndexVec] = computeParentIndex(nameVec)
parentNameVec = computeParentName(nameVec);
[~,parentIndexVec] = ismember(parentNameVec, nameVec);
end
% OUTPUT: parentIndexVec = 1 1 1 2 2 3 5 5
I am now trying to develop a function that essentially acts in reverse, as it takes nameVec and outputs a cell array, which contains at each index, an array of all indices in parentNameVec where the value is that of the output array's ('daughterIndexVec`) current index
function [daughterIndexVec] = computeDaughterIndex(nameVec)
parentIndexVec = computeParentIndex(nameVec);
for i=1:length(parentIndexVec)
daughterIndexVec{i} = find(parentIndexVec==i);
end
end
% OUTPUT: daughterIndexVec = {[1,2,3] [4,5] [6] [] [7,8] [] [] []}
Is there a simpler (more efficient) way to accomplish this without use of for loops?
Any assistance is greatly appreciated!
You can use the second output of ismember to get the locations of each value in parentNameVec in nameVec and then use accumarray to group all indices which share the same index in nameVec together in a cell array.
[~, ind] = ismember(parentNameVec, nameVec);
daughterIndexVec = accumarray(ind(:), 1:numel(ind), [numel(ind) 1], #(x){x.'});
% {[1,2,3] [4,5] [6] [] [7,8] [] [] []}

Finding an element of a structure based on a field value

I have a 1x10 structure array with plenty of fields and I would like to remove from the struct array the element with a specific value on one of the field variables.
I know the value im looking for and the field I should be looking for and I also know how to delete the element from the struct array once I find it. Question is how(if possible) to elegantly identify it without going through a brute force solution ie a for-loop that goes through elements of the struct array to compare with the value I m looking for.
Sample code: buyers as 1x10 struct array with fields:
id,n,Budget
and the variable to find in the id values like id_test = 12
You can use the fact that if you have an array of structs, and you use the dot referencing, this creates a comma-separated list. If you enclose this in [] it will attempt to create an array and if you enclose it in {} it will be coerced into a cell array.
a(1).value = 1;
a(2).value = 2;
a(3).value = 3;
% Into an array
[a.value]
% 1 2 3
% Into a cell array
{a.value}
% [1] [2] [3]
So to do your comparison, you can convert the field you care about into either an array of cell array to do the comparison. This comparison will then yield a logical array which you can use to index into the original structure.
For example
% Some example data
s = struct('id', {1, 2, 3}, 'n', {'a', 'b', 'c'}, 'Budget', {100, 200, 300});
% Remove all entries with id == 2
s = s([s.id] ~= 2);
% Remove entries that have an id of 2 or 3
s = s(~ismember([s.id], [2 3]));
% Find ones with an `n` of 'a' (uses a cell array since it's strings)
s = s(ismember({s.id}, 'a'));

Get indices of string occurrences in cell-array

I have a cell array that contains a long list of strings. Most of the strings are in duplicates. I need the indices of instances of a string within the cell array.
I tried the following:
[bool,ind] = ismember(string,var);
Which consistently returns scalar ind while there are clearly more than one index for which the contents in the cell array matches string.
How can I have a list of indices that points to the locations in the cell array that contains string?
As an alternative to Divakar's comment, you could use strcmp. This works even if some cell doesn't contain a string:
>> strcmp('aaa', {'aaa', 'bb', 'aaa', 'c', 25, [1 2 3]})
ans =
1 0 1 0 0 0
Alternatively, you can ID each string and thus have representative numeric arrays corresponding to the input cell array and string. For IDing, you can use unique and then use find as you would with numeric arrays. Here's how you can achieve that -
var_ext = [var string]
[~,~,idx] = unique(var_ext)
out = find(idx(1:end-1)==idx(end))
Breakdown of the code:
var_ext = [var string]: Concatenate everything (string and var) into a single cell array, with the string ending up at the end (last element) of it.
[~,~,idx] = unique(var_ext): ID everything in that concatenated cell array.
find(idx(1:end-1)==idx(end)): idx(1:end-1) represents the numeric IDs for the cell array elements and idx(end) would be the ID for the string. Compare these IDs and use find to pick up the matching indices to give us the final output.
Sample run -
Inputs:
var = {'er','meh','nop','meh','ya','meh'}
string = 'meh'
Output:
out =
2
4
6
regexp would solve this problem better and the easy way.
string = ['my' 'bat' 'my' 'ball' 'my' 'score']
expression = ['my']
regexp(string,expresssion)
ans = 1 6 12

Difference of two cell arrays of strings in Matlab

I have a cell array like
a={'potential'; 'impact'; 'of'; 'stranded'; 'assets'; 'and'; 'other'; 'necessary'; 'regulatory'; 'approvals'; 'assets'}
and want to subtract from it an array like b={'a'; 'and'; 'of'; 'my'; '#'}.
Using setdiff(a,b) sorts my array after the difference is computed. What I want is to eliminate from a all the elements present in b without sorting a. Also the repetitions should be preserved, for eg. 'assets' in array a should appear at two locations in final array.
The following code I am using does the job:
for i = 1:length(b)
tf = ~strcmp(b(i),a)
a = a(tf,:)
end
But the problem is that array b contains more than 200 string elements which slows down my code considerably. Is there a better way to do this?
tf = ismember(a,b);
a = a(~tf)
EDU>> a
a =
'potential'
'impact'
'of'
'stranded'
'assets'
'and'
'other'
'necessary'
'regulatory'
'approvals'
'assets'
EDU>> b
b =
'a'
'and'
'of'
'my'
'#'
[I,J]=setdiff(a,b);
Now do
EDU>> a(sort(J),:)
ans =
'potential'
'impact'
'stranded'
'other'
'necessary'
'regulatory'
'approvals'
'assets'

How do concatenation and indexing differ for cells and arrays in MATLAB?

I am a little confused about the usage of cells and arrays in MATLAB and would like some clarification on a few points. Here are my observations:
An array can dynamically adjust its own memory to allow for a dynamic number of elements, while cells seem to not act in the same way:
a=[]; a=[a 1]; b={}; b={b 1};
Several elements can be retrieved from cells, but it doesn't seem like they can be from arrays:
a={'1' '2'}; figure; plot(...); hold on; plot(...); legend(a{1:2});
b=['1' '2']; figure; plot(...); hold on; plot(...); legend(b(1:2));
%# b(1:2) is an array, not its elements, so it is wrong with legend.
Are these correct? What are some other different usages between cells and array?
Cell arrays can be a little tricky since you can use the [], (), and {} syntaxes in various ways for creating, concatenating, and indexing them, although they each do different things. Addressing your two points:
To grow a cell array, you can use one of the following syntaxes:
b = [b {1}]; % Make a cell with 1 in it, and append it to the existing
% cell array b using []
b = {b{:} 1}; % Get the contents of the cell array as a comma-separated
% list, then regroup them into a cell array along with a
% new value 1
b{end+1} = 1; % Append a new cell to the end of b using {}
b(end+1) = {1}; % Append a new cell to the end of b using ()
When you index a cell array with (), it returns a subset of cells in a cell array. When you index a cell array with {}, it returns a comma-separated list of the cell contents. For example:
b = {1 2 3 4 5}; % A 1-by-5 cell array
c = b(2:4); % A 1-by-3 cell array, equivalent to {2 3 4}
d = [b{2:4}]; % A 1-by-3 numeric array, equivalent to [2 3 4]
For d, the {} syntax extracts the contents of cells 2, 3, and 4 as a comma-separated list, then uses [] to collect these values into a numeric array. Therefore, b{2:4} is equivalent to writing b{2}, b{3}, b{4}, or 2, 3, 4.
With respect to your call to legend, the syntax legend(a{1:2}) is equivalent to legend(a{1}, a{2}), or legend('1', '2'). Thus two arguments (two separate characters) are passed to legend. The syntax legend(b(1:2)) passes a single argument, which is a 1-by-2 string '12'.
Every cell array is an array! From this answer:
[] is an array-related operator. An array can be of any type - array of numbers, char array (string), struct array or cell array. All elements in an array must be of the same type!
Example: [1,2,3,4]
{} is a type. Imagine you want to put items of different type into an array - a number and a string. This is possible with a trick - first put each item into a container {} and then make an array with these containers - cell array.
Example: [{1},{'Hallo'}] with shorthand notation {1, 'Hallo'}

Resources