Jessica Marie
Jessica Marie

Reputation: 293

Filtering a Cell Array with Recursion

I'm pretty close on this problem. What I have to do is filter out a cell array. The cell array can have a variety of items in it, but what I want to do is pull out the strings, using recursion. I am pretty close on this one. I just have an issue when the cells have spaces in them. This is what I should get:

 Test Cases:

       cA1 = {'This' {{{[1:5] true} {' '}} {'is '} false true} 'an example.'};
       [filtered1] = stringFilter(cA1)
           filtered1 => 'This is an example.'

       cA2 = {{{{'I told '} 5:25 'her she'} {} [] [] ' knows'} '/take aim and reload'};
       [filtered2] = stringFilter(cA2)
           filtered2 => 'I told her she knows/take aim and reload'

Here is what I have:

%find the strings in the cArr and then concatenate them. 
function [Str] = stringFilter(in)
Str = [];
for i = 1:length(in)
    %The base case is a single cell
    if length(in) == 1
        Str = ischar(in{:,:});
    %if the length>1 than go through each cell and find the strings. 
       else
        str = stringFilter(in(1:end-1));
        if ischar(in{i})
            Str = [Str in{i}];
    elseif iscell(in{i}) 
            str1 = stringFilter(in{i}(1:end-1));
            Str = [Str str1];

        end
    end

end

end

I tried to use 'ismember', but that didn't work. Any suggestions? My code outputs the following:

      filtered1 => 'This an example.'
      filtered2 => '/take aim and reload'

Upvotes: 0

Views: 481

Answers (3)

Mohsen Nosratinia
Mohsen Nosratinia

Reputation: 9864

Here is a different implememntation

function str = stringFilter(in)
if ischar(in)
    str = in;
elseif iscell(in) && ~isempty(in)
    str = cell2mat(cellfun(@stringFilter, in(:)', 'uni', 0));
else
    str = '';
end
end

If it's string, return it. If it is a cell apply the same function on all of the elements and concatenate them. Here I use in(:)' to make sure it is a row vector and then cell2mat concatenates resulting strings. And if the type is anything else return an empty string. We need to check if the cell array is empty or not because cell2mat({}) is of type double.

Upvotes: 2

Akshay Rao
Akshay Rao

Reputation: 342

The line

    Str = ischar(in{:,:});

is the problem. It doesn't make any sense to me.

You're close to the getting the answer, but made a few significant but small mistakes.

You need to check for these things: 1. Loop over the cells of the input. 2. For each cell, see if it itself is a cell, if so, call stringFilter on the cell's VALUE 3. if it is not a cell but is a character array, then use its VALUE as it is. 4. Otherwise if the cell VALUE contains a non character, the contribution of that cell to the output is '' (blank)

I think you made a mistake by not taking advantage of the difference between in(1) and in{1}. Anyway, here's my version of the function. It works.

function [out] = stringFilter(in)
out = [];

for idx = 1:numel(in)
    if iscell (in{idx})
        % Contents of the cell is another cell array
        tempOut = stringFilter(in{idx});
    elseif ischar(in{idx})
        % Contents are characters
        tempOut = in{idx};
    else
        % Contents are not characters
        tempOut = '';
    end

    % Concatenate the current output to the overall output
    out = [out, tempOut];
end

end

Upvotes: 1

Nemesis
Nemesis

Reputation: 2334

You can quite simplify your function to

function [Str] = stringFilter(in)
Str = [];
for i = 1:length(in)
    if ischar(in{i})
        Str = [Str in{i}];
    elseif iscell(in{i})
        str1 = stringFilter(in{i});
        Str = [Str str1];
    end
end

end

Just loop through all elements in the cell a test, whether it is a string or a cell. In the latter, call the function for this cell again. Output:

>> [filtered1] = stringFilter(cA1)

filtered1 =

This is an example.

>> [filtered2] = stringFilter(cA2)

filtered2 =

I told her she knows/take aim and reload

Upvotes: 2

Related Questions