Combining array into one string (matlab) - arrays

I have something like the following:
A = [1 2 5; 1 5 7];
B = A(1,:);
I output B:
B = A(1,:);
B =
1 2 5
I am looking to combine what is contained in B into one single string:
1/2/5

You can use sprintf:
sprintf('%d/',B)
This will give you almost what you want, it will have unnecessary / in the end.
>> sprintf('%d/',B)
ans =
1/2/5/
If you want to remove it:
st = sprintf('%d/',B);
st(end) = [];
As #hmuster points out correctly, it is possible to do it with \b , the backspace character.
st = [sprintf('%d/',B) sprintf('\b')];
However, as #AndrewJanke points out correctly, it could become a problem if this string is written into a pipe or a file. So use it with caution.

If you want it done properly (IE reusable), there are two steps:
Convert your numbers to strings (this will allow later crazy values to be converted properly with num2str http://www.mathworks.com/help/matlab/ref/num2str.html
Concatenate your strings horizontally (you can use MATLAB concatenation property A = [B C]), but the functional way is strcat http://www.mathworks.com/help/matlab/ref/strcat.html

Related

How to store the multiple positions of a character in a string inside an array in free format RPGLE?

In standard RPGLE, my code looks like this. This statement stores the positions of the commas in Data in ComArr array.
C ',' Scan Data ComArr
I tried doing it in free format like this. But all the indices of ComArr array is loaded with the first position of comma in Data. This is because %Scan returns only one position and upon saving it to an array ends up loading the whole array with a single value.
ComArr = %Scan(',':Data) ;
Is there any other method to process SCAN in free format RPGLE like it does in C spec? Basically I want to split the string separated by a delimiter.
One possibility is to keep the C-spec as-is. If the code block needs an array of delimiter positions, and one line of code already does that, put a comment above the fixed-format spec describing what it does and leave it in there.
If /free is required and you don't want to replace the entire block of code, you will need to roll your own loop to build the array of delimiters.
I don't personally convert from fixed to /free unless I am re-writing the block of code to be functionally different. That is, I would almost certainly write a different algorithm in /free than I would have written in fixed. So the entire process of building an array of delimiter positions and then splitting the string based on that array is not something I would do in /free.
I would write a new sub-procedure that returns an array of strings given one delimited input string. The code inside that sub-procedure would make one pass through the input, looking for delimiters with %scan(), and for each one found, split the substring into the next available output array element. There's no need for an array of delimiter positions with this sort of algorithm.
This is probably a little late, but if anyone else needs to split a string by a given delimeter, this code should do what you need.
If you assign a value to an array using wildcard eval array(*) = ..., it applies to every element of the array.
Declare the prototype in your source:
D split pr 1024a varying
D string 65535a varying const options(*varsize)
D delims 50a varying const
D pos 10i 0
Declare a couple of variables.
This assumes your input string is 1000 characters and each separated item is 10 characters maximum:
D idx s 10i 0
D list s 1000a
D splitAry s 10a dim(100)
This is how you split the string.
This tells the routine your delimeter is a comma:
c eval idx = 0
c eval splitAry(*) = split(list:',':idx)
Define the procedure that does the work:
*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* split - Split delimited string
*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Psplit b export
D split pi 1024a varying
D iString 65535a varying const options(*varsize)
D iDelims 50a varying const
D iPos 10i 0
*
D result s 1024a varying
D start s 10i 0
D char s 1a
*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
c eval start = iPos + 1
c eval %len(result) = 0
*
c for iPos = start to %len(iString)
c eval char = %subst(iString:iPos:1)
c if %check(iDelims:char) = 1
c eval result = result + char
c else
c leave
c endif
c endfor
*
c return result
Psplit e
Don't forget to add dftactgrp(*no) to your H spec if you're defining and using this in the same module!

Matlab join array of strings

In ruby and other languages, I can create an array, push an arbitrary number of strings and then join the array:
ary=[]
...
ary.push some_str
ary.push some_other_str
...
result = ary.join ""
How do I accomplish this in matlab?
User story: my plot legend is composed of a variable number of strings. The number of strings is determined runtime, so I want to declare the array, add strings dynamically and then join the array to the legend string in the end of the script.
In MATLAB, String joining happens like the following
a = 'ding';
b = 'dong';
c = [a ' ' b]; % Produces 'ding dong'
P.S. a typeof(c,'char') shows TRUE in MATLAB because it "joins" all characters into C.
Suppose you want to start with an empty char placeholder. You can do this.
a = ``; % Produces an empty character with 0x0 size.
Then you can keep adding to the end of it; like this:
a = [a 'newly added'] % produces a = "newly added"
To prove that it works, do this again:
a = [a ' appended more to the end.'] % produces a = "newly added appended more to the end."
You can always use the end keyword that points to the last index of an array, but in this case you need to append to end+X where X is the extra number of characters you are appending (annoyingly). I suggest you just use the [] operator to join/append.
There is also this strjoin(C, delim) function which joins a cell C of strings using a delim delimiter (could be whitespace or whatever). But cheap and dirty one is the one I showed above.

Concatenating 1D matrices of different sizes

I perhaps am going about this wrong, but I have data{1}, data{2}...data{i}. Within each, I have .type1, .type2.... .typeN. The arrays are different lengths, so horizontal concatenation does not work.
For simplicity sake
>> data{1}.type1
ans =
1
2
3
>> data{2}.type1
ans =
2
4
5
6
Results should be [1;2;3;2;4;5;6]
I've been trying to loop it but not sure how? I will have a variable number of files (a,b..). How do I go about looping and concatenating? Ultimately I need a 1xN array of all of this..
My working code, thanks..figured it out..
for i = 1:Types
currentType = nTypes{i}
allData.(currentType)=[];
for j = 1:nData
allData.(currentType) = [allData.(currentType); data{j}.(currentType)(:,3)]; %3rd column
end
end
Look at cat, the first argument is the dimension. In your simple example it would be:
result = cat(1,a,b);
Which is equivalent to:
result = [a;b];
Or you can concatenate them as row vectors and transpose back to a column vector:
result = [a',b']';
For the case of a structure inside a cell array I don't think there will be any way around looping. Let's say you have a cell array with M elements and N "types" as the structure fields for each element. You could do:
M=length(data);
newData=struct;
for i=1:M
for j=1:N
field=sprintf('type%d',j); % //field name
if (M==1), newData.(field)=[]; end % //if this is a new field, create it
newData.(field)=[newData.(field);data{i}.(field)];
end
end

Strcat cell array and array

I have a cell array with strings and a numeric array in Matlab. I want every entry of the cell array to be concatenated with the number from the corresponding position of the array. I think that it can be easily solved using cellfun, but I failed to get it to work.
To clarify, here is an example:
c = {'121' '324' '456' '453' '321'};
array = 1:5
I would like to get:
c = {'1121' '2324' '3456' '4453' '5321'}
A special version of sprintf that outputs directly to a cell array is called sprintfc:
>> C = sprintfc('%d%d',[array(:) str2double(c(:))]).'
C =
'1121' '2324' '3456' '4453' '5321'
It is also a bit different in the way it handles array inputs, by preserving the shape.
You're correct, you can use cellfun – you just need to convert the array to a cell array as well using num2cell. Assuming array is a vector of integers:
c = {'121' '324' '456' '453' '321'};
array = 1:5;
c2 = cellfun(#(c,x)[int2str(x) c],c,num2cell(array),'UniformOutput',false)
which returns
c2 =
'1121' '2324' '3456' '4453' '5321'
In your case, you can also accomplish the same thing just using cell2mat and mat2cell:
c2 = mat2cell([int2str(array(:)) cell2mat(c.')],ones(1,length(array))).'
Another one-liner, this one without undocumented functions (with thanks to #chappjc for showing me the "format" input to num2str):
strcat(num2str(array(:),'%-d'),c(:)).'

Breaking up a string and then converting to a vector?

If I have three strings, such as 'Y20194', '219Y42', and '12345' how do I break these up into a vector like [Y 2 0 1 9 4], [1 2 3 4 5], and [2 1 9 Y 4 2]? I am using str2num, but I think I am missing a step (separating the individual numbers in the strings first) before I convert to numerical values. Also, the characters aren't reading correctly and using str2num gives me [].
I have a file with lines of strings such as the one above. I used fgetl to read each line of my file into strings but am kind of stuck beyond that.
You cannot have both characters and numbers in a numerical vector.
You can do the following:
s = 'Y20194';
c = cellstr(s')';
v = str2double(c);
Cell array c will have all the characters from s separated in to individual cells. Notice that you have to transpose the string s first.
In vector v the first value will be NaN since it's a character.
The char will be kept. and the numbers will be converted to double type.
If the input is not from reading a file, the code is as follows. The result1 is the cell containing the array you want:
If the input is one file, let's take this file as example: demo1.txt, which content as follows:
the codes to convert each line to what you want as follows. the code converts each line into what you want and then display it.
If you want to replace the 'Y' or other alphabets with zero, then the code will be as follows
Maybe STRSPLIT will help.
ts = strsplit('Y20194');
% ts <- {'Y', '2', '0', '1', '9', '4'}
And now you can try to convert each element in the vector individually to a number using str2num.
N = size(ts, 1);
str = cell(1, N);
for i=1:N;
str{i} = str2num(ts{i, 1});
end
But since some of the characters in the string aren't numbers (e.g., 'Y'), I wouldn't expect this to work perfectly.
(Its been a while, some of my indexes may be switched.)
If you want to change the Y into 0 a very simple solution is available:
str = 'Y20194';
str(str==Y)='0';
str - '0'

Resources