How do you search for a number in a cell array containing different length arrays?
1 view (last 30 days)
Show older comments
Is there a way to search for an element inside a cell array? I have the following cell array:
1×10 cell array
Columns 1 through 5
{[2 5 8 9]} {[1 2 4 5 7 10]} {[3 5 6 7 8 9 10]} {[1 2 3 5 8 9 10]} {[1 2 4 6 8 9]}
Columns 6 through 10
{[1 3 4 5 6 8]} {[1 2 4]} {[4 5 7 9]} {[1 2 5 7 10]} {[1 2 3 4 6 8]}
I'm trying to determine the index of the array that contains a number, such as 1 for example. So for this example 1 is in array elements 2, 4, 5, 6, 7,9 and 10.
0 Comments
Accepted Answer
Dyuman Joshi
on 28 Nov 2023
in = {[2 5 8 9] [1 2 4 5 7 10] [3 5 6 7 8 9 10] [1 2 3 5 8 9 10] [1 2 4 6 8 9] [1 3 4 5 6 8] [1 2 4] [4 5 7 9] [1 2 5 7 10] [1 2 3 4 6 8]}
idx = find(cellfun(@(x) ismember(1, x), in))
2 Comments
Dyuman Joshi
on 28 Nov 2023
Though, the fastest approach would be to use a for loop.
in = {[2 5 8 9] [1 2 4 5 7 10] [3 5 6 7 8 9 10] [1 2 3 5 8 9 10] [1 2 4 6 8 9] [1 3 4 5 6 8] [1 2 4] [4 5 7 9] [1 2 5 7 10] [1 2 3 4 6 8]};
vec = 1:numel(in);
%Lazy preallocation
z = vec~=0;
for k=vec
z(k) = any(in{k}==1);
end
z
out = vec(z)
Dyuman Joshi
on 28 Nov 2023
Some timings -
%Generate random data
vec = randi([25 50], 1, 50000);
s = sum(vec)
arr = randi([1 100], 1, s);
in = mat2cell(arr, 1, vec);
f1 = @(x) funloop(x);
f2 = @(x) funcellany(x);
f3 = @(x) funcellismember(x);
F1 = @() f1(in);
F2 = @() f2(in);
F3 = @() f3(in);
%Check for equality first
isequal(F1(), F2(), F3())
fprintf('Time taken by for loop = %f seconds', timeit(F1))
fprintf('Time taken by cellfun and any() = %f seconds', timeit(F2))
fprintf('Time taken by cellfun and ismember() = %f seconds', timeit(F3))
As can be observed, for loop is atleast 10x faster than both of the cellfun() methods.
function out = funloop(in)
vec = 1:numel(in);
%Lazy preallocation
z = vec~=0;
for idx=vec
z(idx) = any(in{idx}==1);
end
out = vec(z);
end
function out = funcellany(in)
f=@(x) any(x==1);
out = find(cellfun(f,in));
end
function out = funcellismember(in)
out = find(cellfun(@(x) ismember(1, x), in));
end
More Answers (2)
Voss
on 28 Nov 2023
C = {[2 5 8 9], [1 2 4 5 7 10], [3 5 6 7 8 9 10], [1 2 3 5 8 9 10], [1 2 4 6 8 9], [1 3 4 5 6 8], [1 2 4], [4 5 7 9], [1 2 5 7 10], [1 2 3 4 6 8]}
val = 1; % value to check for
One way is to write a for loop to check each element of C for whether its contents contain a 1 (or whatever value):
nC = numel(C);
has_val = false(1,nC);
for ii = 1:nC
has_val(ii) = any(C{ii} == val);
end
has_val
result = find(has_val)
Another way is to let cellfun do the loop for you:
has_val = cellfun(@(v)any(v == val),C)
result = find(has_val)
0 Comments
Fangjun Jiang
on 28 Nov 2023
a=[{[2 5 8 9]} {[1 2 4 5 7 10]} {[3 5 6 7 8 9 10]} {[1 2 3 5 8 9 10]} {[1 2 4 6 8 9]},...
{[1 3 4 5 6 8]} {[1 2 4]} {[4 5 7 9]} {[1 2 5 7 10]} {[1 2 3 4 6 8]}]
f=@(x) any(x==1);
find(cellfun(f,a))
0 Comments
See Also
Categories
Find more on Resizing and Reshaping Matrices in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!