How do I only loop through certain parts of a cell array? - string

I am trying to figure out a way to make a for loop in which I can compare two cells that will give me two different means. One for class char and the other for class double.
This is what I have so far.
V = {2; 'tree'; 3; 'hope'};
W = {2; 'tree'; 3; 'hope'};
for i = 1:length(V);
if isequal(class(V{i}), 'double')
num = V{i}
elseif isequal(class(V{i}), 'char')
str = V{i}
end
end
for i = 1:length(W);
if isequal(class(W{i}), 'double')
acc_n(i) = isequal(V{i}, W{i})
elseif isequal(class(W{i}), 'char')
acc_s(i) = strcmp(V{i}, W{i})
end
end
mean_d = mean(acc_n)
mean_s = mean(acc_s)
The output I get is:
acc_n =
1 0 1
acc_s =
0 1 0 1
mean_d =
0.6667
mean_s =
0.5000
The output I want is:
1 1 for string, mean = 1. 1 1 for double, mean = 1
How can I do a loop where it only takes the numbers of the cell and the words of the cell separately?
Is there any possible way to only loop through the words or the numbers?

You can first extract strings and doubles and treat them separately, that will avoid loops.
V = {2; 'tree'; 3; 'hope'};
W = {2; 'tree'; 3; 'hope'};
VChar=V(cellfun(#ischar,V));
WChar=W(cellfun(#ischar,W));
acc_s=VChar==WChar;
VNum=cell2mat(V(cellfun(#isnumeric,V)));
WNum=cell2mat(W(cellfun(#isnumeric,W)));
acc_n=VNum==WNum;
Loop version: I haven't tested this but it should work.
%Assumes V and W have equal number of elements.
acc_n=[];
acc_s=[];
for i=1:numel(V)
if isequal(class(V{i}), 'double') && isequal(V{i},W{i})
acc_n=[acc_n true];
elseif isequal(class(V{i}), 'char') && strcmp(V{i},W{i})
acc_s=[acc_s true];
end
end

Related

Replace not working with SAP Gui Scripting retrieved data

So I created a scripting to retrieve data from SAP Gridview object to an Excel sheet. Some columns I needed to replace some characters because this data is consumed by a Power Bi report. For example:
4,350.00 will be replaced for the value 4350. So I do two replaces, the first removing the . and the second replacing the , with .
The problem is that the replace is being applied in every data retrieved. Here's the code.
For i = 0 To GridView.RowCount - 1
For j = 0 To GridView.ColumnCount - 1
shtInput.Cells(z + i, j + 1) = GridView.GetCellValue(i, GridView.ColumnOrder(j))
If j > 8 And j < 19 Then:
rep = GridView.GetCellValue(i, GridView.ColumnOrder(j))
rep = replace(rep, ".", "")
rep = replace(rep, ",", ".")
shtInput.Cells(z + i, j + 1) = rep
Next j
shtInput.Cells(z + i, Area) = "Finance"
If i Mod 32 = 0 Then
GridView.SetCurrentCell i, CStr(Columns(0))
GridView.firstVisibleRow = i
End If
Next i
There's a data column that the script capture the value 21.02.2021 and replace it with 21,02,2021.

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.

replace fraction with decimal in Excel using vbscript

As part of a larger script, I am trying to replace fraction values with decimal values in excel using vbscript. I can always count on the values to have a specific column and a specific format.
Excel example expected input column B:
51-7/16
1-1/2
2
15-7/8
Excel example desired output column B:
51.4375
1.5
2
15.875
I know it will always be to a 1/16th. So my idea was to go through the list looking for each possible fraction, find a cell that contains that fraction, and replace it with the corresponding decimal.
Questions: How do I tell the script to find a cell that contains a value and how do I replace that fraction with the decimal?
closest example Search and Replace a number of characters in Excel using VBscript
Attempt:
Dim FMember (14)
FMember(0) = "-1/16"
FMember(1) = "-1/8"
FMember(2) = "-3/16"
FMember(3) = "-1/4"
FMember(4) = "-5/16"
FMember(5) = "-3/8"
FMember(6) = "-7/16"
FMember(7) = "-1/2"
FMember(8) = "-9/16"
FMember(9) = "-5/8"
FMember(10) = "-11/16"
FMember(11) = "-3/4"
FMember(12) = "-13/16"
FMember(13) = "-7/8"
FMember(14) = "-15/16"
Dim DMember(14)
DMember(0) = ".0625"
DMember(1) = ".125"
DMember(2) = ".1875"
DMember(3) = ".25"
DMember(4) = ".3125"
DMember(5) = ".375"
DMember(6) = ".4375"
DMember(7) = ".5"
DMember(8) = ".5625"
DMember(9) = ".625"
DMember(10) = ".6875"
DMember(11) = ".75"
DMember(12) = ".8125"
DMember(13) = ".875"
DMember(14) = ".9375"
Dim endRow2
endRow2 = objSheet2.UsedRange.Rows.Count
For lngPosition = LBound(FMember) To UBound(FMember)
For r = 1 To endRow2
If objSheet2.Cells(r, objSheet2.Columns("B").Column).Value = FMember(lngPosition) Then
objSheet2.replace
End If
Next
Next
Use split()
Function fract(str As String) As Double
Dim strArr() As String
If InStr(str, "-") Then
strArr = Split(str, "-")
fract = strArr(0) + Application.Evaluate(strArr(1))
Else
fract = Application.Evaluate(str)
End If
End Function
Then you can use it as a worksheet function:
=fract(A1)

Compare to string of names

I am trying to compare the names of two strings, and trying to pick out the name that are not included in the other string.
h = 1;
for i = 1:name_size_main
checker = 0;
main_name = main(i);
for j = 1:name_size_image
image_name = image(j);
temp = strcmpi(image_name, main_name);
if temp == 1;
checker = temp;
end
end
if checker == 0
result(h) = main_name;
h = h+1;
end
end
but it keeps returning the entire string as result, the main string contain roughly 1000 names, the images name contain about 300 names, so it should return about 700 names in result but it keep returning all 1000 names.
I tried your code with small vectors:
main = ['aaa' 'bbb' 'ccc' 'ddd'];
image = ['bbb' 'ddd'];
name_size_main = size(main,2);
name_size_image = size(image,2);
h = 1;
for i = 1:name_size_main
checker = 0;
main_name = main(i);
for j = 1:name_size_image
image_name = image(j);
temp = strcmpi(image_name, main_name);
if temp == 1;
checker = temp;
end
end
if checker == 0
result(h) = main_name;
h = h+1;
end
end
I get result = 'aaaccc', is it not what you want to get?
EDIT:
If you are using cell arrays, you should change the line result(h) = main_name; to result{h} = main_name; like that:
main = {'aaa' 'bbb' 'ccc' 'ddd'};
image = {'bbb' 'ddd'};
name_size_main = size(main,2);
name_size_image = size(image,2);
result = cell(0);
h = 1;
for i = 1:name_size_main
checker = 0;
main_name = main(i);
for j = 1:name_size_image
image_name = image(j);
temp = strcmpi(image_name, main_name);
if temp == 1;
checker = temp;
end
end
if checker == 0
result{h} = main_name;
h = h+1;
end
end
You can use cells of string along with setdiff or setxor.
A = cellstr(('a':'t')') % a cell of string, 'a' to 't'
B = cellstr(('f':'z')') % 'f' to 'z'
C1 = setdiff(A,B,'rows') % gives 'a' to 'e'
C2 = setdiff(B,A,'rows') % gives 'u' to 'z'
C3 = setxor(A,B,'rows') % gives 'a' to 'e' and 'u' to 'z'

Return all subsequences of a String

I'm trying to write pseudo-code and an algorithm in Matlab, to return all the subsequences of a string.
So the string X = {ABCD} will return XSubSequence = {A, B, C, D, AB, AC, AD, BC, BD, CD, ABC, ABD, BCD, ABCD}, order does not matter of course.
clear
x = 'ABC';
XSize = length(x);
count = 1;
i=1;
for i=1:XSize
ZSubSequence{count} = x(i);
count = count + 1;
for j=i+1:XSize
temp = strcat(x(i),x(j));
ZSubSequence{count} = temp;
count = count + 1;
for k=i+2:XSize
if j ~= k
temp = strcat(x(i), x(j), x(k));
ZSubSequence{count} = temp;
count = count + 1;
end
end
end
end
Is there any way to make this more dynamic, so I can add X of any size and it will be able to deal with it?
You might want to consider a completely different approach.
This this is a binary representation of decimal numbers from 1 to 2^length(x)-1. Meaning for your example 1100=12 will be AB and 0011=3 will be CD, 1000 will be A and 1111=2^4-1=15 will be ABCD and so on.
You might want to create this sequence and then translate it into the input output you have.
Example code:
x = 'ABCD';
XSize = length(x);
seq=dec2bin([1:2^XSize-1]);
And now all have left is translate it back to letters
for i=1:1:2^XSize-1
for j=1:1:XSize
if seq(i,j)=='1'
seq(i,j)=x(j);
else
seq(i,j)='_';
end
end
end
Obviously the '_' should be removed and the output formatted the way you want them to be.
This should do it. It only has one loop (no nesting), so it shoud be pretty fast.
x = 'ABCD';
n = length(x);
subseq = x.';
for ii = 2:n
subseq = strvcat(subseq, x(nchoosek(1:n,ii)));
end
subseq_deblanked = deblank(mat2cell(subseq, ones(size(subseq,1),1), n));
The results are:
subseq: char matrix where each row contains a subsequence padded with blank spaces.
subseq_deblanked: cell array of strings with the blank spaces removed, as you specified

Resources