Is there an Octave equivalent of Matlab's `contains` function? - matlab

Is there an equivalent of MATLAB's contains function in Octave? Or, is there a simpler solution than writing my own function in Octave to replicate this functionality? I am in the process of switching to Octave from MATLAB and I use contains throughout my MATLAB scripts.

Let's stick to the example from the documentation on contains: In Octave, there are no (double-quoted) strings as introduced in MATLAB R2017a. So, we need to switch to plain, old (single-quoted) char arrays. In the see also section, we get a link to strfind. We'll use this function, which is also implemented in Octave to create an anonymous function mimicking the behaviour of contains. Also, we will need cellfun, which is available in Octave, too. Please see the following code snippet:
% Example adapted from https://www.mathworks.com/help/matlab/ref/contains.html
% Names; char arrays ("strings") in cell array
str = {'Mary Ann Jones', 'Paul Jay Burns', 'John Paul Smith'}
% Search pattern; char array ("string")
pattern = 'Paul';
% Anonymous function mimicking contains
contains = #(str, pattern) ~cellfun('isempty', strfind(str, pattern));
% contains = #(str, pattern) ~cellfun(#isempty, strfind(str, pattern));
TF = contains(str, pattern)
The output is as follows:
str =
{
[1,1] = Mary Ann Jones
[1,2] = Paul Jay Burns
[1,3] = John Paul Smith
}
TF =
0 1 1
That should resemble the output of MATLAB's contains.
So, in the end - yes, you need to replicate the functionality by yourself, since strfind is no exact replacement.
Hope that helps!
EDIT: Use 'isempty' instead of #isempty in the cellfun call to get a faster in-built implementation (see carandraug's comment below).

I'm not too familiar with MuPad functions, but it looks like this is reinventing the ismember function (which exists in both Matlab and Octave).
E.g.
ismember( {'jim', 'stan'}, {'greta', 'george', 'jim', 'jenny'} )
% ans = 1 0
i.e. 'jim' is a member of {'greta', 'george', 'jim', 'jenny'}, whereas 'stan' is not.
Furthermore, ismember also supports finding the index of the matched element:
[BoolVal, Idx] = ismember( {'jim', 'stan'}, {'greta', 'george', 'jim', 'jenny'} )
% BoolVal = 1 0
% Idx = 3 0

Personally I use my own implementation, which returns 1 if a string str contains entire substring sub:
function res = containsStr(str, sub)
res = 0;
strCharsCount = length(str);
subCharsCount = length(sub);
startCharSub = sub(1);
% loop over character of main straing
for ic = 1:strCharsCount
currentChar = str(ic);
% if a substring starts from current character
if (currentChar == startCharSub)
%fprintf('Match! %s = %s\n', currentChar, startCharSub);
matchedCharsCount = 1;
% loop over characters of substring
for ics = 2:subCharsCount
nextCharIndex = ic + (ics - 1);
% if there's enough chars in the main string
if (nextCharIndex <= strCharsCount)
nextChar = str(nextCharIndex);
nextCharSub = sub(ics);
if (nextChar == nextCharSub)
matchedCharsCount = matchedCharsCount + 1;
end
end
end
%fprintf('Matched chars = %d / %d\n', matchedCharsCount, subCharsCount);
% the substring is inside the main one
if (matchedCharsCount == subCharsCount)
res = 1;
end
end
end
end

Related

Matlab Create MD5 Checksum for Variables

For debugging, i wish to compare several objects, and create some unique ID for each them, and according its contents and structure, the ID should be equal. Is there any existing function for doing this?
For example if an object is an structure:
S:
S.a1 = 1
S.a2 = 2
S.b1 = 3
S.b11 = 4
S.b12 = 5
S.c1 = 6
My current choice is copying it to the disk and calculate a MD5 64-bit checksum, which do not work because this hash depends on the modified date of the file.
One solution is mentioned here. DataHash function is that solution:
function H = DataHash(Data)
Engine = java.security.MessageDigest.getInstance('MD5');
H = CoreHash(Data, Engine);
H = sprintf('%.2x', H); % To hex string
function H = CoreHash(Data, Engine)
% Consider the type of empty arrays:
S = [class(Data), sprintf('%d ', size(Data))];
Engine.update(typecast(uint16(S(:)), 'uint8'));
H = double(typecast(Engine.digest, 'uint8'));
if isa(Data, 'struct')
n = numel(Data);
if n == 1 % Scalar struct:
F = sort(fieldnames(Data)); % ignore order of fields
for iField = 1:length(F)
H = bitxor(H, CoreHash(Data.(F{iField}), Engine));
end
else % Struct array:
for iS = 1:n
H = bitxor(H, CoreHash(Data(iS), Engine));
end
end
elseif isempty(Data)
% No further actions needed
elseif isnumeric(Data)
Engine.update(typecast(Data(:), 'uint8'));
H = bitxor(H, double(typecast(Engine.digest, 'uint8')));
elseif ischar(Data) % Silly TYPECAST cannot handle CHAR
Engine.update(typecast(uint16(Data(:)), 'uint8'));
H = bitxor(H, double(typecast(Engine.digest, 'uint8')));
elseif iscell(Data)
for iS = 1:numel(Data)
H = bitxor(H, CoreHash(Data{iS}, Engine));
end
elseif islogical(Data)
Engine.update(typecast(uint8(Data(:)), 'uint8'));
H = bitxor(H, double(typecast(Engine.digest, 'uint8')));
elseif isa(Data, 'function_handle')
H = bitxor(H, CoreHash(functions(Data), Engine));
else
warning(['Type of variable not considered: ', class(Data)]);
end
Also, you can find the complete version of the code here.
A more general solution than #OmG 's answer, that relies on a little bit of undocumented functionality:
function str = hash(in)
% Get a bytestream from the input. Note that this calls saveobj.
inbs = getByteStreamFromArray(in);
% Create hash using Java Security Message Digest.
md = java.security.MessageDigest.getInstance('SHA1');
md.update(inbs);
% Convert to uint8.
d = typecast(md.digest, 'uint8');
% Convert to a hex string.
str = dec2hex(d)';
str = lower(str(:)');
The undocumented function getByteStreamFromArray returns the byte stream that would be written to disk if you were to call the save -v7 command on the variable. It works for any variable that is less than 2GB in size, including not only the built-in types (numeric, logical, struct, cell etc.) covered by #OmG 's CoreHash, but also built-in and user-defined classes as well.
Note that getByteStreamFromArray calls saveobj, so it will ignore Transient properties - this is almost certainly a good thing for hashing as well as saving.
PS In either solution, SHA1 is probably better than MD5.

How can I write a MATLAB function named kellen that takes three input arguments named trs, ch1,ch2?

Problem description:
trs takes a row or column vector of string, and two characters as ch1 and ch2. If ch1 is matched with any element in trs then that element of trs will be replaced by ch2. If ch1 is not in the vector, trs will be returned as unchanged.
A simple example:
Input: ww = kellen({‘YOYO’, ‘YOYO’},’Y’,’X’),
output: ww = {‘XOXO’,’XOXO’}
I assume strrep function could make this problem easier but I would like to know the very basic level how MATLAB can handle this problem without using strrep function. So I request you guys please correct my code without using strrepfunction.
I am new to MATLAB. Indeed, I am new to programming too. I know I had to learn C first for basic but I did not that why is I am to struggle.
Here is my code but it seems do not work.
function ww = kellen(trs,ch1,ch2)
[r c] = size(trs);
if r == 1 && c > 1
for i = 1:c
ind = trs{i} == ch1;
trs{1,i}(ind==1) = ch2;
ww = trs;
end
if r == 1 && c ==1
for i = 1:c
ind = trs{i} == ch1;
trs{1,i}(ind==1) = ch2;
ww = trs
end
end
My code works fine when size of string vector is row vector but my function is not working fine when i pass scalar of trs string. For instance:
kellen({ 'peter piper picked a peck of pickled peppers' }, 'p', 'b')
Which part of my code should i modify?
for i = 1:c
if trs{i} == 'c1'
outp = [trs 'c2'];
else
return
end
end
The first problem I see with your code is the line: if trs{i} == 'c1'
There are a lot of problems here:
By putting '...' quotes around ch1 you are making ch1 a string literal, NOT the variable for character one that was passed into your function. Drop the quotes. This is the source of your error, attempting to equate a 4 character string with a 3 character string.
You are equating a whole string trs{i} with a single character ch1. You can do that in Matlab, but NOT in an if statement. Let's take your example inputs, trs{1} is 'YOYO' and if we try 'YOYO'=='Y' we get a logical vector like [1 0 1 0]. Now if expects just a 1 or 0 and not a vector.
So I would suggest dropping the if statement and taking advantage of Matlab's logical indexing instead:
outp{c} = []; %// this is just preallocation
for i = 1:c
temp = trs{i};
idx = temp==ch1 %// Get a logical matrix of which characters match
temp(idx)=ch2; %// Use logical indexing to replace all the characters that match in this string in one go!
outp{i} = temp;
end
Once you understand this code you can simplify:
outp = trs;
for i = 1:c
outp{i}(outp{i}==ch1)=ch2
end
You can use ismember() to find the locations where ch1 is present in trs. So, in fact trs(ismember(trs,ch1)) = ch2; will replace all instances of ch1 with ch2 in trs.
However, you need to make sure that ch1 and ch2 are exactly one characters long. If you want to have trs as a cell of strings, like in your question, than you can either loop through it the way you do now, or you can take a look at the cellfun() function.

Matlab function return value

I have one program that has function and the problem, return value, it has too many output.
Like exempley: y = text the answer comes up
Error in text (line 2)
if nargin == 0
Output argument "array" (and maybe others) not assigned during call to "
C:\Users\name\Documents\MATLAB\text.m>text".
The program text.m reads a txt file that contains a couple of names and numbers like
exemple:
John doughlas 15986
Filip duch 357852
and so on. The program convert them to 15986 Doughlas John and so on.
function array = text(~)
if nargin == 0
dirr = '.';
end
answer = dir(dirr);
k=1;
while k <= length(answer)
if answer(k).isdir
answer(k)=[];
else
filename{k}=answer(k).name;
k=k+1;
end
end
chose=menu( 'choose file',filename);
namn = char(filename(chose));
fid = fopen(namn, 'r');
R = textscan(fid,'%s %s %s');
x=-1;
k=0;
while x <= 24
x = k + 1;
All = [R{3}{x},' ',R{1}{x},' ',R{2}{x}];
disp(All)
k = k + 1;
end
fclose(fid);
Is there anyway to fix the problem without starting over from scratch?
Grateful for all the answers!
You specify the function output argument in the definition, but you don't assign anything to it in the function body.
For example, in
function y = student(j)
your output is y. So you have to assign something to y.
Read more about functions in MATLAB.
Here is a working example.
The first part is to create a function called 'functionA' in a filename 'functionA.m'. Then put the following code inside:
function result = functionA(N,alpha)
result = 5;
return
end
The second part is to create another Matlab file(i.e. upto you to name it) or you can use the Matlab command window even. Then run the following code:
getresult = functionA(100,10);
getresult
After running you get the following answer:
ans =
5

Function, in MATLAB dna replication

I'm trying to figure out the function command in Matlab and im having some difficulties.
I'm trying to write a Matlab function named dna_replicate. It will replicate a given strand and return its partner strand
For example if the user enters ATGCATGCAHGCAGTC, it should return TACGTACGT CGTCAG
A-->T
G-->C if the user enters other than these 4 letters, there should be blank in the partner strand. Thank you for your help
This implementation should be faster, involving only a simple table look-up. Note that the table t is constructed only once when the function is first called.
function out = dna_replicate(in)
persistent t
if isempty(t)
t = blanks(256);
t('ATGC') = 'TACG';
end
out = t(in);
end
How about:
function out = dna_replicate(in)
in = upper(in); % Ensures all same case
A = in=='A';
T = in=='T';
C = in=='C';
G = in=='G';
out = in;
out(A) = 'T';
out(T) = 'A';
out(C) = 'G';
out(G) = 'C';
out(~(A|T|C|G)) = ' ';
while #Jirka cigler answer works, it uses a for loop as well as dynamically growing vector 'out'. As matlab is optimized for vector operations, this answer should perform better.
You can create a simple vectorized solution using the function ISMEMBER:
function outString = dna_replicate(inString)
[~,index] = ismember(upper(inString),'ACGT'); %# Find the indices of inStrings
%# letters in string `ACGT`
outString = 'ACGT '; %# Initialize outString to `ACGT` and a blank
outString = outString(5-index); %# Use inverted and shifted index to expand
%# outString to the size of inString
end
And here's a test:
>> dna_replicate('ATGCATGCAHGCAGTC')
ans =
TACGTACGT CGTCAG
I think it can be implemented as follows:
function out=dna_replicate(in)
for i=1:numel(in)
switch in(i)
case 'A'
out(i)= 'T';
case 'G'
out(i)= 'C';
case 'T'
out(i)='A';
case 'C'
out(i)='G';
otherwise
out(i)=' ';
end
end
this function has argument of type char
in='ATGCATGCAHGCAGTC'
and you can run
out=dna_replicate(in)
to get the same result as you want :-)

How do I display strings and numbers together in MATLAB?

I have a 500-by-1 matrix of strings S and a 500-by-1 matrix of numbers N. I want to see them in the variable editor together like this:
S(1) N(1)
S(2) N(2)
...
S(500) N(500)
Is this possible?
The following should allow you to look at the variables together in the Command Window:
disp([char(S) blanks(numel(N))' num2str(N)]);
The array S (which I presume is a cell array) is converted to a character array using the function CHAR. It's then concatenated with a column vector of blanks (made using the function BLANKS) and then a string representation of the numeric array N (made using the function NUM2STR). This is then displayed using the function DISP.
Speaking narrowly to your question, just convert the numbers to cells. You'll have a single variable that the array editor can handle.
X = [ S num2cell(N) ];
More broadly, here's an array-oriented variant of sprintf that's useful for displaying records constructed from parallel arrays. You'd call it like this. I use something like this for displaying tabular data a lot.
sprintf2('%-*s %8g', max(cellfun('prodofsize',S)), S, N)
Here's the function.
function out = sprintf2(fmt, varargin)
%SPRINTF2 Quasi-"vectorized" sprintf
%
% out = sprintf2(fmt, varargin)
%
% Like sprintf, but takes arrays of arguments and returns cellstr. This
% lets you do formatted output on nonscalar arrays.
%
% Example:
% food = {'wine','cheese','fancy bread'};
% price = [10 6.38 8.5];
% sprintf2('%-12s %6.2f', food, price)
% % Fancier formatting with width detection
% sprintf2('%-*s %6.2f', max(cellfun('prodofsize',food)), food, price)
[args,n] = promote(varargin);
out = cell(n,1);
for i = 1:n
argsi = grab(args, i);
out{i} = sprintf(fmt, argsi{:});
end
% Convenience HACK for display to command line
if nargout == 0
disp(char(out));
clear out;
end
function [args,n] = promote(args)
%PROMOTE Munge inputs to get cellstrs
for i = 1:numel(args)
if ischar(args{i})
args{i} = cellstr(args{i});
end
end
n = cellfun('prodofsize', args);
if numel(unique(n(n > 1))) > 1
error('Inconsistent lengths in nonscalar inputs');
end
n = max(n);
function out = grab(args, k)
%GRAB Get the kth element of each arg, popping out cells
for i = 1:numel(args)
if isscalar(args{i})
% "Scalar expansion" case
if iscell(args{i})
out{i} = args{i}{1};
else
out{i} = args{i};
end
else
% General case - kth element of array
if iscell(args{i})
out{i} = args{i}{k};
else
out{i} = args{i}(k);
end
end
end