match check in matlab - string

i have strings like these:
s{1,2} = 'string';
s{2,2} = 'string2';
and in workspace structure like this
U.W.string = [2 2.5 3]
I want to check (in loop) s{1,2} or s{2,2} or s{i,2} matches any structure with the same name. If so, assign values from this structure to some variable var(i). How can it be done?

Use isfields to check, if a string is the name of a field in a struct. Then use the syntax struct.(name), where name is a string to access the field. Your code might look something like:
test = struct('hello', 'world', 'count', 42, 'mean', 10);
fields = {'test', 'count';
'hello', 'text';
'more', 'less'};
values = {pi, 'dummy', -1};
for row = 1 : size(fields, 1)
for column = 1 : size(fields, 2)
if isfield(test, fields{row, column})
test.(fields{row, column}) = values{row};
end
end
end
This converts the initial struct
test =
hello: 'world'
count: 42
mean: 10
to this one
test =
hello: 'dummy'
count: 3.1416
mean: 10
A shorter implementation is achieved by removing the inner loop and giving a cell-array to isfields:
for row = 1 : size(fields, 1)
%# Note the parenthesis instead of curly braces in the next statement.
match = isfield(test, fields(row, :));
if any(match)
test.(fields{row, match}) = values{row};
end
end

Use isfield(structName,fieldName). This should do the trick:
strings{1,1} = 'foo';
strings{1,2} = 'bar';
strings{1, 3} = 'foobar';
U.W.foo = 1;
U.W.foobar = 5;
for idx = 1:length(strings)
if(isfield(U.W,strings{1,idx}))
expression = sprintf('outvar(idx) = U.W.%s',strings{1,idx});
eval(expression);
end
end

Related

how to extract an integer range from a string

I have a string that contains different ranges and I need to find their value
var str = "some text x = 1..14, y = 2..4 some text"
I used the substringBefore() and substringAfter() methodes to get the x and y but I can't find a way to get the values because the numbers could be one or two digits or even negative numbers.
One approach is to use a regex, e.g.:
val str = "some text x = 1..14, y = 2..4 some text"
val match = Regex("x = (-?\\d+[.][.]-?\\d+).* y = (-?\\d+[.][.]-?\\d+)")
.find(str)
if (match != null)
println("x=${match.groupValues[1]}, y=${match.groupValues[2]}")
// prints: x=1..14, y=2..4
\\d matches a single digit, so \\d+ matches one or more digits; -? matches an optional minus sign; [.] matches a dot; and (…) marks a group that you can then retrieve from the groupValues property. (groupValues[0] is the whole match, so the individual values start from index 1.)
You could easily add extra parens to pull out each number separately, instead of whole ranges.
(You may or may not find this as readable or maintainable as string-manipulation approaches…)
Is this solution fit for you?
val str = "some text x = 1..14, y = 2..4 some text"
val result = str.replace(",", "").split(" ")
var x = ""; var y = ""
for (i in 0..result.count()-1) {
if (result[i] == "x") {
x = result[i+2]
} else if (result[i] == "y") {
y = result[i+2]
}
}
println(x)
println(y)
Using KotlinSpirit library
val rangeParser = object : Grammar<IntRange>() {
private var first: Int = -1
private var last: Int = -1
override val result: IntRange
get() = first..last
override fun defineRule(): Rule<*> {
return int {
first = it
} + ".." + int {
last = it
}
}
}.toRule().compile()
val str = "some text x = 1..14, y = 2..4 some text"
val ranges = rangeParser.findAll(str)
https://github.com/tiksem/KotlinSpirit

How to extract substrings with different lengths?

I have an n by 2 matrix that contains start and end indices of substrings of a specified string. How can I extract the n by 1 cell array of substrings without a for-loop?
string = 'Hello World!';
ranges = [1 1;
2 3;
4 5;
3 7];
substrings = cell(size(ranges, 1), 1);
for i=1:size(ranges, 1)
substrings{i} = string(ranges(i, 1):ranges(i, 2));
end
The expected result:
substrings =
'H'
'el'
'lo'
'llo W'
You can use cellfun to make it a single-line operation:
str = 'Hello World!';
ranges = [ 1 1;
2 3;
4 5;
3 7];
% first convert "ranges" to a cell object
Cranges = mat2cell(ranges,ones(size(ranges,1),1),2);
% call "cellfun" on every row/entry of "Cranges"
cellfun(#(x)str(x(1):x(2)),Cranges, 'UniformOutput',false)
ans =
4×1 cell array
{'H' }
{'el' }
{'lo' }
{'llo W'}
I have changed the variable string to str because string is a native function in MATLAB (converting the input to the type string).
Although this is single-line operation, it doesn't mean that it is more efficient:
Num = 1000000;
substrings = cell(size(ranges, 1), 1);
% time for-loop
tic
for j = 1:Num
for i = 1:size(ranges, 1)
substrings{i} = str(ranges(i, 1):ranges(i, 2));
end
end
toc;
Cranges = mat2cell(ranges,ones(size(ranges,1),1),2);
% time function-call
tic
for j = 1:Num
substrings = cellfun(#(x)str(x(1):x(2)),Cranges, 'UniformOutput',false);
end
toc;
Elapsed time is 3.929622 seconds.
Elapsed time is 50.319609 seconds.

Adding a Value to All Numbers in a Text in NodeJS

I would to substitute all numbers in a text, for instance I would to add some value V to all numbers. For example, for V=3:
var inp = "Try to replace thsis [11-16] or this [5] or this [1,2]";
the substitution should give me:
var output = "Try to replace thsis [14-19] or this [8] or this [4,5]";
With RegExp I would like to do some like:
var V = 12;
var re = new RegExp(/[0-9]+/g);
var s = inp.replace(re,'$1' + V);
but obviously does not work.
In in.replace(re,'$1' + V), the V value is just added to $1 string, and the string replacement pattern looks like $112. Since your pattern does not contain any capturing group, the replacement pattern is treated as a literal string.
You may use a callback inside the replace method where you may manipulate the match value:
var V = 3;
var inp = "Try to replace thsis [11-16] or this [5] or this [1,2]";
var re = /[0-9]+/g;
var outp = inp.replace(re, function($0) { return parseInt($0, 10) + V; });
console.log(outp);

Mean of one variable when another variable equals 1 in matlab

I would like to get the mean of my reaction time column when my stimnum column is equal to 1
I am not sure if i can do this with one simple line of code or if i need to do a for loop.
stimnum = randi([1 3], [1 100]);
y = 1 + 1.*randn(1, 100);
rt = (y.^2) +.01;
A = rand(1,100);
correct = A>=0.2;
Data= [stimnum; rt; correct ]';
Data = dataset({ Data, 'Stimnum', 'RT', 'Correct'});
rtmean = mean (Data.RT{Data.Stimnum == 1});

How to define a partial copy constructor metaprogramically in Julia?

Gadfly has a nifty macro that generates a copy constructor and optional argument constructor for some large types:
# Generate large types where each field has a default value to which it's
# initialized.
macro varset(name::Symbol, table)
#assert table.head == :block
table = table.args
names = Any[]
vars = Any[]
parameters = Any[]
parameters_expr = Expr(:parameters)
for row in table
if isa(row, Expr) && row.head == :line
continue
end
if isa(row, Symbol)
var = row
typ = :Any
default = :nothing
elseif row.head == :tuple
#assert 2 <= length(row.args) <= 3
var = row.args[1]
typ = row.args[2]
default = length(row.args) > 2 ? row.args[3] : :nothing
else
error("Bad varset systax")
end
push!(names, var)
push!(vars, :($(var)::$(typ)))
push!(parameters, Expr(:kw, var, default))
parameters_expr = Expr(:parameters, parameters...)
end
new_with_defaults = Expr(:call, :new, names...)
ex =
quote
type $(name)
$(vars...)
function $(name)($(parameters_expr))
$(new_with_defaults)
end
# shallow copy constructor
function $(name)(a::$(name))
b = new()
for name in fieldnames($(name))
setfield!(b, name, getfield(a, name))
end
b
end
end
function copy(a::$(name))
$(name)(a)
end
end
esc(ex)
end
I would like to add a partial copy constructor that lets you provide an object and some partial parameters. It would copy the provided object and overwrite only the fields that you give it.
How could I define something like the following? Pseudocode-ish:
function $(name)(a::$(name), $(parameters_expr))
b = new(a)
for name in names
if getfield(b, name) != default
setfield!(b, name, new_val)
end
end
end

Resources