fullSeq='ABCDEFG'
Inputcell= {'ABC', 'BDEG','DEFG','ABCDEFG','CDEG','BCDF','ABCDEFG'}
I have 2 'ABCDEFG' strings in the above Inputcell. How can I remove those 2 strings? The expected output should be:
Outputcell= {'ABC', 'BDEG','DEFG','CDEG','BCDF'}
You can use logical indexing along with strcmp:
OutputCell = Inputcell(~strcmp(Inputcell,fullSeq))
OutputCell =
'ABC' 'BDEG' 'DEFG' 'CDEG' 'BCDF'
yay!
Simple call to ismember will do the trick combined with logical indexing:
fullSeq='ABCDEFG';
Inputcell= {'ABC', 'BDEG','DEFG','ABCDEFG','CDEG','BCDF','ABCDEFG'};
Outputcell = Inputcell(~ismember(Inputcell, fullSeq));
We get:
>> Outputcell
Outputcell =
'ABC' 'BDEG' 'DEFG' 'CDEG' 'BCDF'
If for some reason you want to automatically delete every element which appears at least twice (rather than having to run the above answers with various values of fullSeq), you can do that too:
iif = #(varargin) varargin{2*find([varargin{1:2:end}], 1, 'first')}(); %define inline 'if'
Inputcell={'ABC', 'BDEG','DEFG','ABCDEFG','CDEG','BCDF','ABCDEFG'};
Tempcell=cellfun(#(x)iif(sum(strcmp(x,Inputcell))>1,[],true,x),Inputcell,...
'uniformoutput',false);
Outputcell=Tempcell(~cellfun('isempty',Tempcell))
Result:
Outputcell =
'ABC' 'BDEG' 'DEFG' 'CDEG' 'BCDF'
Related
I have the following cell array:
>> tmp0 = {'foo', '%s', 'one'; 'bar', '%d', 3}
tmp0 =
2×3 cell array
'foo' '%s' 'one'
'bar' '%d' [ 3]
I can use it like this with sprintf:
>> sprintf('%s,%d', tmp0{:,3})
ans =
'one,3'
I would like to be able to achieve the same thing with a function call, since if I have a function that generates a cell array, say genCell(), I don't think I can achieve something like genCell(){:} in MATLAB.
So I made this function:
function cellExp(cellIn)
cellIn{:}
end
Although dubious it seems to work as expected so far, since calling cellExp(tmp0(:,3)) seems to be the same as calling tmp0{:,3}
>> cellExp(tmp0(:,3))
ans =
'one'
ans =
3
>> tmp0{:,3}
ans =
'one'
ans =
3
However, ultimately, I cannot use it as desired:
>> sprintf('%s,%d', cellExp(tmp(:,3)))
Error using cellExp
Too many output arguments.
The last error message you are getting is because the output of cellExp(tmp0(:,3)) is comma-separeted list.
I am not sure exactly what you are looking for here, but I think this is one possibility for a function that will return your string based on a myCell = tmp0.
function myStr = mySprintf(myCell)
formatSpec = strjoin(myCell(:,2), ',');
[A1, A2] = myCell{:, 3};
myStr = sprintf(formatSpec, A1, A2);
end
I want to build a file name from cell arrays. I wanted to use sprintf function, but it doesn't work for cell inputs (it works well for example for string arrays).
Example:
foldername = sprintf('''\\STH\\Sth %s\\ABC %s;'',firstvariable,secondvariable);
Output:
Error using sprintf
Function is not defined for 'cell' inputs.
Where variables are cell arrays, like that:
firstvariable = {'A','B','C'};
secondvariable = {'D','E','F'};
I also tried to use fullfile function, but it doesn't take any variables. The output from this one look like that: \STH\Sth %s\ABC %s. What more, I also tried to use strcat function, but the result is pretty the same.
Do you have any other ideas how it can be done?
Thanks!
You can pass the two cell arrays to cellfun to loop over them at the same time:
firstvariable = {'A','B','C'};
secondvariable = {'D','E','F'};
foldername = cellfun(#(x,y) ['\STH\Sth ' x '\ABC ' y], firstvariable, secondvariable, 'UniformOutput', false);
This gives
foldername =
1×3 cell array
'\STH\Sth A\ABC D' '\STH\Sth B\ABC E' '\STH\Sth C\ABC F'
Is this what you want?
for ii = 1:length(firstvariable)
foldername{ii} = sprintf('''\\STH\\Sth %s\\ABC %s;''',firstvariable{ii},secondvariable{ii});
end
The output is:
foldername = {''\STH\Sth A\ABC D;''} {''\STH\Sth B\ABC E;''} {''\STH\Sth C\ABC F;''}
To use any of the folder names just do the following:
foldername{index} % Gives back a string
foldername(index) % Gives back a cell
Here's a non-scalar structure in matlab:
clearvars s
s=struct;
for id=1:3
s(id).wa='nko';
s(id).test='5';
s(id).ad(1,1).treasurehunt='asdf'
s(id).ad(1,2).treasurehunt='as df'
s(id).ad(1,3).treasurehunt='foobar'
s(id).ad(2,1).treasurehunt='trea'
s(id).ad(2,2).treasurehunt='foo bar'
s(id).ad(2,3).treasurehunt='treasure'
s(id).ad(id,4).a=magic(5);
end
is there an easy way to test if the structure s contains the string 'treasure' without having to loop through every field (e.g. doing a 'grep' through the actual content of the variable)?
The aim is to see 'quick and dirtily' whether a string exists (regardless of where) in the structure. In other words (for Linux users): I'd like to use 'grep' on a matlab variable.
I tried arrayfun(#(x) any(strcmp(x, 'treasure')), s) with no success, output:
ans =
1×3 logical array
0 0 0
One general approach (applicable to any structure array s) is to convert your structure array to a cell array using struct2cell, test if the contents of any of the cells are equal to the string 'treasure', and recursively repeat the above for any cells that contain structures. This can be done in a while loop that stops if either the string is found or there are no structures left to recurse through. Here's the solution implemented as a function:
function found = string_hunt(s, str)
c = reshape(struct2cell(s), [], 1);
found = any(cellfun(#(v) isequal(v, str), c));
index = cellfun(#isstruct, c);
while ~found && any(index)
c = cellfun(#(v) {reshape(struct2cell(v), [], 1)}, c(index));
c = vertcat(c{:});
found = any(cellfun(#(c) isequal(c, str), c));
index = cellfun(#isstruct, c);
end
end
And using your sample structure s:
>> string_hunt(s, 'treasure')
ans =
logical
1 % True!
This is one way to avoid an explicit loop
% Collect all the treasurehunt entries into a cell with strings
s_cell={s(1).ad.treasurehunt, s(2).ad.treasurehunt, s(3).ad.treasurehunt};
% Check if any 'treasure 'entries exist
find_treasure=nonzeros(strcmp('treasure', s_cell));
% Empty if none
if isempty(find_treasure)
disp('Nothing found')
else
disp(['Found treasure ',num2str(length(find_treasure)), ' times'])
end
Note that you can also just do
% Collect all the treasurehunt entries into a cell with strings
s_cell={s(1).ad.treasurehunt, s(2).ad.treasurehunt, s(3).ad.treasurehunt};
% Check if any 'treasure 'entries exist
find_treasure=~isempty(nonzeros(strcmp('treasure', s_cell)));
..if you're not interested in the number of occurences
Depending on the format of your real data, and if you can find strings that contain your string:
any( ~cellfun('isempty',strfind( arrayfun( #(x)[x.ad.treasurehunt],s,'uni',0 ) ,str)) )
I'd like to achieve the following using dynamic fieldnames instead of setfield:
Say a struct 'myStruct' has a set of nested structures, i.e.
myStruct.a.b.c = 0
myStruct.a.d = 0
myStruct.a.e.f.g = 0
I want to be able to flexibly set the leaf structure values as follows:
fields = {'a', 'b', 'c'}
paramVal = 1
setfield(myStruct, fields{:}, paramVal)
This works using setfield. Is there a syntax that will do this using dynamic fieldnames? The following obviously doesn't work because the fieldname needs to be a string not an array, but demonstrates what I want:
myStruct.(fields{:}) = 0
Which would be equivalent to:
myStruct.('a').('b').('c') = 0
Recursive solution without eval, ripped from one of my old utility functions:
function s = setsubfield(s, fields, val)
if ischar(fields)
fields = regexp(fields, '\.', 'split'); % split into cell array of sub-fields
end
if length(fields) == 1
s.(fields{1}) = val;
else
try
subfield = s.(fields{1}); % see if subfield already exists
catch
subfield = struct(); % if not, create it
end
s.(fields{1}) = setsubfield(subfield, fields(2:end), val);
end
I guess the try/catch can be replaced with if isfield(s, fields{1}) ..., I don't remember why I coded it like that.
Usage:
>> s = struct();
>> s = setsubfield(s, {'a','b','c'}, 55);
>> s = setsubfield(s, 'a.b.d.e', 12)
>> s.a.b.c
ans =
55
>> s.a.b.d.e
ans =
12
Below is a simple, if crude, solution that works for scalar structs. Applying it to your example,
S=setfld(myStruct,'a.b.c',1)
>> S.a.b.c
ans =
1
In general, though, deeply nested structs are unrecommended.
function S=setfld(S,fieldpath,V)
%A somewhat enhanced version of setfield() allowing one to set
%fields in substructures of structure/object S by specifying the FIELDPATH.
%
%Usage: setfld(S,'s.f',V) will set S.s.f=V
%
%
%%Note that for structure S, setfield(S.s,'f') would crash with an error if
%S.s did not already exist. Moreover, it would return a modified copy
%of S.s rather than a modified copy of S, behavior which would often be
%undesirable.
%
%
%Works for any object capable of a.b.c.d ... subscripting
%
%Currently, only single structure input is supported, not structure arrays.
try
eval(['S.' fieldpath '=V;']);
catch
error 'Something''s wrong.';
end
Suppose I have a series of strings such as:
a = '101010101010'
b = '010101'
c = '000101010'
is there a way in Matlab to concatenate them and produce the binary number 101010101010010101000101010?
Use the concatenation operator [ ], with horizontal concatenation , (vertical concatenation ; will fail here unless you reshape() into column vectors):
[a,b,c]
However, I suggest storing your variables in a cell array:
s = {'101010101010','010101', '000101010'};
[s{:}]
or
cat(2,s{:})
To concatenate strings, you could say:
out = [a b c];
Alternatively:
out = strcat(a,b,c);
Yet another way:
out = sprintf('%s', a,b,c);
I think that this should work:
res = [a,b,c]
or alternatively call
res = strcat(a,b,c)
or, yet
res = cat(2,a,b,c)