MATLAB concatenate string variables - string

I know strjoin can be used to concatenate strings, like 'a' and 'b' but what if one of the strings is a variable, like
a=strcat('file',string(i),'.mat')
and I want:
strjoin({'rm',a})
MATLAB throws an error when I attempt this, and it's driving me crazy!
Error using strjoin (line 53) First input must be a string array or cell array of character vectors

What version of MATLAB are you using? What is the error? The first input to strjoin needs to be a cell array. Try strjoin({'rm'},a).
Also, before 17a, do:
a = strcat('file', num2str(i),'.mat')
In >=17a do:
a = "file" + i + ".mat";
Here is a performance comparison:
function profFunc
tic;
for i = 1:1E5
a = strcat('file', num2str(i),'.mat');
end
toc;
tic;
for i = 1:1E5
a = "file" + i + ".mat";
end
toc;
end
>> profFunc
Elapsed time is 6.623145 seconds.
Elapsed time is 0.179527 seconds.

Related

How to specify last character in 1 cell ( Inside IF )

i have a code that copies and rewrites anything thats between "(" and ")", but now i have different type of data which do not end with ")" so, i need it to stop when it reaches the last character in cell. Maybe it is dumb question but i cant seem to find how to fix my problem. I am a student and total newbie in vba (5 days ago i didn't know what vba is...) also sorry for my bad english.
I've tried to search (in here, google, youtube) but i couldnt find anything i need
'zaciatok=start koniec=end dlzka=length
Do While Mid(LookInHere, y, 1) <> ""
If Mid(LookInHere, Z, 1) = "(" Then
zaciatok = Z
End If
If Mid(LookInHere, y, 1) = ")" Then
koniec = y
dlzka = (koniec - 1) - zaciatok
dlzka = Abs(dlzka)
SplitCatcher = Mid(LookInHere, zaciatok + 1, CStr(dlzka))
MsgBox SplitCatcher
End If
y = y + 1
Z = Z + 1
Loop
In your specific implementation, one option is to modify your Do While ... loop to also test against the length of the string. That line would look something like:
Do While Mid(LookInHere, y, 1) <> "" And y < Len(LookInHere)
That modification tells the statement that it should terminate the loop when the iterating variable y goes past the length of the statement.
Another option is to change it from a Do While loop to a For loop. It would read something like:
For i = 1 to Len(LookInHere)
MsgBox Mid(LookInHere, i, 1)
'Input your logic here
Next i
The problem is that each of these versions is relatively inefficient, looping through each letter in a string a performing a calculation. Consider using built-in Excel functions. The Instr returns the position of a character, or a zero if it is not found. As an example, Instr("Abcdef", "b") would return the number 2, and Instr("Abcdef", "k") would return zero. You can replace the entire loop with these two function calls.
Z = Instr(LookInHere, "(")
y = Instr(LookInHere, ")")
If y = 0 Then y = Len(LookInHere)
Final note: if your patterns begin to get more and more complex, consider reviewing and implementing regular expressions.
You can use Right(LookInHere, 1) to get the last character of LookInHere

find location of string in matrix

I want to find the location of 'N' in a matrix. After this I want to replace that 'N' with the median of that vector in the matrix. I already used these codes for this but I get several errors.
%% put test data in matrix
k=1;
m=1;
n=3;
for j=1:99
percentage2 = j/99
mDataTest(m,1) = str2double(data{1}{j});
mDataTest(m,2) = 0;
for i = 3:50
percentage1 = j/50
if(strcmp(data{i}{j},''))
mDataTest(m,i) = 'N'; %give each "" the median value
elseif(strcmp(data{i}{j},'NULL'))
mDataTest(m,i) = 'N'; %give each "NULL" the median value
else
mDataTest(m,i) = str2double(data{i}{j}); %make matrix with data
end
end
m=m+1;
n=3;
end
Index = find(contains(mDataTest,'N'));
for i = 1 :50
vMedian=median(vDataTest(:,i));
end
mDataTest(Index)= vMedian(Index(2));
Here I use the 'contains' function but I get errors.
Is there someone that can help me?
Thanks!
Your code seems a bit strange to me. Let me try to understand what it is you want to do.
So you start out with a 2D cell variable with text and you want to convert it to a numeric matrix. When cells are empty or contain 'NULL' you want them to have the median value of the row that they are in.
I would start with the conversion and make the empty and 'NULL' cells NaN. (Not a Number) Then find alle the nans and use median with the omitnan flag to replace the nans.
for j=1:99
for i = 1:50
if(strcmp(data{i}{j},'')||strcmp(data{i}{j},'NULL'))
mDataTest(j,i) = nan; %replace with nan
else
mDataTest(j,i) = str2double(data{i}{j}); %convert to number
end
end
end
for j=1:99
for i = 1:50
if isnan(mDataTest(j,i))
mDataTest(j,i) = median(mDataTest(j,:),'omitnan')
end
end
end

contains with separate result for each of multiple patterns

Matlab's documentation for the function TF = contains(str,pattern) states:
If pattern is an array containing multiple patterns, then contains returns 1 if it finds any element of pattern in str.
I want a result for each pattern individually however.
That is:
I have string A='a very long string' and two patterns B='very' and C='long'. I want to check if B is contained in A and if C is contained in A. I could do it like this:
result = false(2,1);
result(1) = contains(A,B);
result(2) = contains(A,C);
but for many patterns this takes quite a while. What is the fast way to do this?
I don't know or have access to that function; it must be "new", so I don't know its particular idiosyncrasies.
How I would do that is:
result = ~cellfun('isempty', regexp(A, {B C}));
EIDT
Judging from the documentation, you can do the exact same thing with contains:
result = contains(A, {B C});
except that seems to return contains(A,B) || contains(A,C) rather than the array [contains(A,B) contains(A,C)]. So I don't know, I can't test it here. But if all else fails, you can use the regex solution above.
The new text processing functions in 16b are the fastest with string. If you convert A to a string you may see much better performance.
function profFunc
n = 1E6;
A = 'a very long string';
B = 'very';
C = 'long';
tic;
for i = 1:n
result(1) = contains(A,B);
result(2) = contains(A,C);
end
toc;
tic;
for i = 1:n
x = regexp(A, {B,C});
end
toc;
A = string(A);
tic;
for i = 1:n
result(1) = contains(A,B);
result(2) = contains(A,C);
end
toc;
end
>> profFunc
Elapsed time is 7.035145 seconds.
Elapsed time is 9.494433 seconds.
Elapsed time is 0.930393 seconds.
Questions: Where do B and C come from? Do you have a lot of hard coded variables? Can you loop? Looping would probably be the fastest. Otherwise something like
cellfun(#(x)contains(A,x),{B C})
is an option.

String sub not working correctly

I've got yet another question about lua. I've created a method to calculate the total amount of some prices. The prices are in this format: £500. So to convert them to numbers I'm using string:sub() and tonumber(), but I'm getting some weird results. Here is my code:`
function functions.calculateTotalAmount()
print("calculating total amount")
saveData.totalAmount = 0
print("There are " .. #saveData.amounts .. " in the amount file")
for i=1, #saveData.names do
print("SaveData.amounts[" .. i .. "] original = " .. saveData.amounts[i])
print("SaveData.amounts[" .. i .. "] after sub= " .. saveData.amounts[i]:sub(2))
print("totalAmount: " .. saveData.totalAmount)
if saveData.income[i] then
saveData.totalAmount = saveData.totalAmount + tonumber(saveData.amounts[i]:sub(2))
else
saveData.totalAmount = saveData.totalAmount - tonumber(saveData.amounts[i]:sub(2))
end
end
totalAmountStr.text = saveData.totalAmount .. " " .. currencyFull
loadsave.saveTable(saveData, "payMeBackTable.json")
end
I printed out some info in the for loop to determine the problem and this is what is being printed for the first 2 print statements in the for loop:
16:03:51.452 SaveData.amounts1 original = ¥201
16:03:51.452 SaveData.amounts1 after sub= 201
It looks fine here in stackoverflow but for the the ¥ is actually not gone in my log, instead it is replaced with a weird rectangle symbol. There will be a picture of the printed text attached to this post.
Does anyone see what is going on here?
Don't use sub in this case as the ¥ sign is likely a multi-byte sequence (depending on the encoding), so using sub(2) you are cutting it in the middle instead of removing it.
Use gsub("[^%d%.]+","") instead to remove all non-numeric parts.
string.sub() works on the bytes of a string, not on its chars. There is a difference when the string contains Unicode text.
If the number is at the end of the string, extract it with
amount = tonumber(saveData.amounts[i]:match("%d+$"))
Lua strings are strings of bytes, not strings of characters. ASCII characters are 1 byte long, but most other characters consume multiple bytes, so using string.sub() isn't going to work.
There are several standards for converting between bytes and characters (or code points), but by far the most common on the web is UTF-8. If you are using Lua 5.3 or greater, you can use new built-in functions for performing UTF-8 manipulation. For example, to take a substring of a UTF-8 string, you can do:
-- Simple version without bounds-checking.
function utf8_sub1(s, start_char_idx, end_char_idx)
start_byte_idx = utf8.offset(s, start_char_idx)
end_byte_idx = utf8.offset(s, end_char_idx + 1) - 1
return string.sub(s, start_byte_idx, end_byte_idx)
end
-- More robust version with bounds-checking.
function utf8_sub2(s, start_char_idx, end_char_idx)
start_byte_idx = utf8.offset(s, start_char_idx)
end_byte_idx = utf8.offset(s, end_char_idx + 1)
if start_byte_idx == nil then
start_byte_idx = 1
end
if end_byte_idx == nil then
end_byte_idx = -1
else
end_byte_idx = end_byte_idx - 1
end
return string.sub(s, start_byte_idx, end_byte_idx)
end
s = "¥201"
print(string.sub(s, 2, 4)) -- an invalid byte sequence
print(utf8_sub1(s, 2, 4)) -- "201"
print(utf8_sub2(s, 2, 4)) -- "201"
print(utf8_sub1(s, 2, 5)) -- throws an error
If you don't have Lua 5.3, you can use a UTF-8 library like this one instead to achieve the same functionality.

How to split data and save min value of startTime to variable

i wan't to create the script which can save from csv startTime and endTime to variable, for example i have different startTime values(11:59:12, 11:59:19, 11:59:22) and different endTime values (12:59:12, 12:59:19, 12:59:22), i want to store for startTime to varible only lowest one, which has been started early than others and endTime which has been ended last.
So from this examples must be stored to variable startTime = 11:59:12 and endTime = 11:59:22.
Could you tell me please what i gonna do. my script looks right now like that:
import csv
import datetime
import time
data = list(csv.reader(open('C:\\Documents and Settings\\Lemur\\Desktop\\TestResults.csv', 'r')))
startTimeWithoutCp = ""
for x in xrange(4, 13):
cpStartTime = (data[x][6])+ ":" + " " + (data[x][12][10:19])
cpEndTime = (data[x][6])+ ":" + " " + (data[x][13][10:19])
startTimeWithoutCp += (data[x][12][11:19])
#print("CP Start Times is: ", cpStartTime)
#print("CP End Time is: ", cpEndTime)
print(startTimeWithoutCp)
# The output results looks like that:
# 11:59:0811:59:1211:59:1911:59:2211:59:2811:59:3211:59:3711:59:4211:59:47
Could you tell me please, how i can split correctly this results and get minimal value from this list. Thank you!
First of all, I think you should store your time points in a list. Concatenating them into one string (like you do it for startTimeWithoutCp) makes it hard to get back the original times. On individual time points, you can use the fact that strings / characters can be sorted:
>>> a = '11:20:02'
>>> b = '04:34:12'
>>> c = '04:34:14'
>>> sorted([a, b, c])
['04:34:12', '04:34:14', '11:20:02']
>>> min([a, b, c])
'04:34:12'
So given you have your time points in a list, you can just use min() and max().
You can split the long string into its pieces by using Python's slicing notation:
d = '11:59:0811:59:1211:59:1911:59:2211:59:2811:59:3211:59:3711:59:4211:59:47'
print([d[i:i + 8] for i in range(0, len(d), 8)])

Resources