Easytrieve - Removing leading zero in numeric variable - mainframe

Using Easytrieve program am trying to fetch the details from DB2. But one off the column is having integer datatype and am moving the data to binary variable.
And I need to perform arithmetic operation in this variable and result will be move to output file.
When i try to move binary value to alpha numeric am getting leading zero.
Not sure how to remove those leading value.
For example :
DB2 column name (Period_value) = 240
Easytrieve :
FILE TEMP1
TEMP-PERIOD 1 5 A
WS-VAL1 W 4 B 0
WS-TEMP W 4 N
....
....
using cursor to get the value from Db2
WS-VAL1 is holding the value 240
DISPLAY WS-VAL1 => OUTPUT : 240
* CALCULATION
WS-VAL1 = WS-VAL1 + 1
WS-TEMP = WS-VAL1
DISPLAY WS-TEMP -> OUTPUT : 0241
MOVE WS-TEMP to TEMP-PERIOD
PUT TEMP1
But output file contains
0241
Expected output
241
242 (without leading zero)
Could someone help me on this.

Related

Matlab Split-String

Hello,
I have a little problem.
I have a txt file with over 200mb.
It looks like:
%Hello World
%second sentences
%third;
%example
12.02.2014
;-400;-200;200
;123;233;434
%Hello World
%second sentences
%third
%example
12.02.2014
;-410;200;20300
;63;23;43
;23;44;78213
..
... ...
I need only the Values after the semicolon like:
Value1{1,1}=[-400]; Value{1,2}=[-200]; and Value{1,3}=[200]
Value2{1,1}=[123]; Value{1,2}=[233]; and Value{1,3}=[434]
and so on.
Hase someone an ideas, how i can split the values in a cell array or vektor?
Thus, the variables must be:
Var1=[-400 -200 200;
434 233 434;
Var2=[
-410 200 20300;
63 23 43;
23 44 28213]
I will seperate, after every date in a another Value. Example when i have 55 Dates, i will have 55 Values.
shareeditundeleteflag
This could be one approach assuming a uniformly structured data (3 valid numbers per row) -
%// Read in entire text data into a cell array
data = importdata('sample.txt','');
%// Remove empty lines
data = data(~cellfun('isempty',data))
%// Find boundaries based on delimiter "%example"
exmp_delim_matches = arrayfun(#(n) strcmp(data{n},'%example'),1:numel(data))
bound_idx = [find(exmp_delim_matches) numel(exmp_delim_matches)]
%// Find lines that start with delimiter ";"
matches_idx = find(arrayfun(#(n) strcmp(data{n}(1),';'),1:numel(data)))
%// Select lines that start with character ";" and split lines based on it
%// Split selected lines based on the delimiter ";"
split_data = regexp(data(matches_idx),';','split')
%// Collect all cells data into a 1D cell array
all_data = [split_data{:}]
%// Select only non-empty cells and convert them to a numeric array.
%// Finally reshape into a format with 3 numbers per row as final output
out = reshape(str2double(all_data(~cellfun('isempty',all_data))),3,[]).' %//'
%// Separate out lines based on the earlier set bounds
out_sep = arrayfun(#(n) out(matches_idx>bound_idx(n) & ...
matches_idx<bound_idx(n+1),:),1:numel(bound_idx)-1,'Uni',0)
%// Display results for verification
celldisp(out_sep)
Code run -
out_sep{1} =
-400 -200 200
123 233 434
out_sep{2} =
-410 200 20300
63 23 43
23 44 78213
A brute force approach would be to open up your file, then read each line one at a time. With each line, you check to see if the first character is a semi-colon and if it is, split up the string by the ; delimiter from the second character of the line up until the end. You will receive a cell array of strings, so you'd have to convert this into an array of numbers. Because you will probably have each line containing a different amount of numbers, let's store each array into a cell array where each element in this cell array will contain the numbers per line. As such, do something like this. Let's assume your text file is stored in text.txt:
fid = fopen('text.txt');
if fid == -1
error('Cannot find file');
end
nums = {};
while true
st = fgetl(fid);
if st == -1
break;
end
if st(1) == ';'
st_split = strsplit(st(2:end), ';');
arr = cellfun(#str2num, st_split);
nums = [nums arr];
end
end
Let's go through the above code slowly. We first use fopen to open up the file for reading. We check to see if the ID returned from fopen is -1 and if that's the case, we couldn't find or open the file so spit out an error. Next, we declare an empty cell array called nums which will store our numbers that you are getting when parsing your text file.
Now, until we reach the end of the file, get one line of text starting from the top of the file and we proceed to the end. We use fgetl for this. If we read a -1, this means we have reached the end of the file, so get out of the loop. Else, we check to see if the first character is ;. If it is, then we take a look at the second character until the end of this line, and split the string based on the ; character with strsplit. The result of this will be a cell array of strings where each element is the string representation of your number. You need to convert this cell array back into a numeric array, and so what you would need to do is apply str2num to each element in this cell. You can either use a loop to go through each cell, or you can conveniently use [cellfun](http://www.mathworks.com/help/matlab/ref/cellfun.html to allow you to go through each element in this cell and convert the string representation into a numeric value. The resulting output of cellfun will give you a numeric array representation of each value delimited by the ; character for that line. We then place this array into a single cell stored in nums.
The end result of this entire code will give you numeric arrays that are based on what you are looking for stored in nums.
Warning
I am assuming that your text file only has numbers delimited by ; characters if we encounter a line that starts with ;. If this is not the case, then my code will not work. I'm assuming this isn't the case!

Count number of occurences of a string and relabel

I have a n x 1 cell that contains something like this:
chair
chair
chair
chair
table
table
table
table
bike
bike
bike
bike
pen
pen
pen
pen
chair
chair
chair
chair
table
table
etc.
I would like to rename these elements so they will reflect the number of occurrences up to that point. The output should look like this:
chair_1
chair_2
chair_3
chair_4
table_1
table_2
table_3
table_4
bike_1
bike_2
bike_3
bike_4
pen_1
pen_2
pen_3
pen_4
chair_5
chair_6
chair_7
chair_8
table_5
table_6
etc.
Please note that the dash (_) is necessary Could anyone help? Thank you.
Interesting problem! This is the procedure that I would try:
Use unique - the third output parameter in particular to assign each string in your cell array to a unique ID.
Initialize an empty array, then create a for loop that goes through each unique string - given by the first output of unique - and creates a numerical sequence from 1 up to as many times as we have encountered this string. Place this numerical sequence in the corresponding positions where we have found each string.
Use strcat to attach each element in the array created in Step #2 to each cell array element in your problem.
Step #1
Assuming that your cell array is defined as a bunch of strings stored in A, we would call unique this way:
[names, ~, ids] = unique(A, 'stable');
The 'stable' is important as the IDs that get assigned to each unique string are done without re-ordering the elements in alphabetical order, which is important to get the job done. names will store the unique names found in your array A while ids would contain unique IDs for each string that is encountered. For your example, this is what names and ids would be:
names =
'chair'
'table'
'bike'
'pen'
ids =
1
1
1
1
2
2
2
2
3
3
3
3
4
4
4
4
1
1
1
1
2
2
names is actually not needed in this algorithm. However, I have shown it here so you can see how unique works. Also, ids is very useful because it assigns a unique ID for each string that is encountered. As such, chair gets assigned the ID 1, followed by table getting assigned the ID of 2, etc. These IDs will be important because we will use these IDs to find the exact locations of where each unique string is located so that we can assign those linear numerical ranges that you desire. These locations will get stored in an array computed in the next step.
Step #2
Let's pre-allocate this array for efficiency. Let's call it loc. Then, your code would look something like this:
loc = zeros(numel(A), 1);
for idx = 1 : numel(names)
id = find(ids == idx);
loc(id) = 1 : numel(id);
end
As such, for each unique name we find, we look for every location in the ids array that matches this particular name found. find will help us find those locations in ids that match a particular name. Once we find these locations, we simply assign an increasing linear sequence from 1 up to as many names as we have found to these locations in loc. The output of loc in your example would be:
loc =
1
2
3
4
1
2
3
4
1
2
3
4
1
2
3
4
5
6
7
8
5
6
Notice that this corresponds with the numerical sequence (the right most part of each string) of your desired output.
Step #3
Now all we have to do is piece loc together with each string in our cell array. We would thus do it like so:
out = strcat(A, '_', num2str(loc));
What this does is that it takes each element in A, concatenates a _ character and then attaches the corresponding numbers to the end of each element in A. Because we want to output strings, you need to convert the numbers stored in loc into strings. To do this, you must use num2str to convert each number in loc into their corresponding string equivalents. Once you find these, you would concatenate each number in loc with each element in A (with the _ character of course). The output is stored in out, and we thus get:
out =
'chair_1'
'chair_2'
'chair_3'
'chair_4'
'table_1'
'table_2'
'table_3'
'table_4'
'bike_1'
'bike_2'
'bike_3'
'bike_4'
'pen_1'
'pen_2'
'pen_3'
'pen_4'
'chair_5'
'chair_6'
'chair_7'
'chair_8'
'table_5'
'table_6'
For your copying and pasting pleasure, this is the full code. Be advised that I've nulled out the first output of unique as we don't need it for your desired output:
[~, ~, ids] = unique(A, 'stable');
loc = zeros(numel(A), 1);
for idx = 1 : numel(names)
id = find(ids == idx);
loc(id) = 1 : numel(id);
end
out = strcat(A, '_', num2str(loc));
If you want an alternative to unique, you can work with a hash table, which in Matlab would entail to using the containers.Map object. You can then store the occurrences of each individual label and create the new labels on the go, like in the code below.
data={'table','table','chair','bike','bike','bike'};
map=containers.Map(data,zeros(numel(data),1)); % labels=keys, counts=values (zeroed)
new_data=data; % initialize matrix that will have outputs
for ii=1:numel(data)
map(data{ii}) = map(data{ii})+1; % increment counts of current labels
new_data{ii} = sprintf('%s_%d',data{ii},map(data{ii})); % format outputs
end
This is similar to rayryeng's answer but replaces the for loop by bsxfun. After the strings have been reduced to unique labels (line 1 of code below), bsxfun is applied to create a matrix of pairwise comparisons between all (possibly repeated) labels. Keeping only the lower "half" of that matrix and summing along rows gives how many times each label has previously appeared (line 2). Finally, this is appended to each original string (line 3).
Let your cell array of strings be denoted as c.
[~, ~, labels] = unique(c); %// transform each string into a unique label
s = sum(tril(bsxfun(#eq, labels, labels.')), 2); %'// accumulated occurrence number
result = strcat(c, '_', num2str(x)); %// build result
Alternatively, the second line could be replaced by the more memory-efficient
n = numel(labels);
M = cumsum(full(sparse(1:n, labels, 1)));
s = M((1:n).' + (labels-1)*n);
I'll give you a psuedocode, try it yourself, post the code if it doesn't work
Initiate a counter to 1
Iterate over the cell
If counter > 1 check with previous value if the string is same
then increment counter
else
No- reset counter to 1
end
sprintf the string value + counter into a new array
Hope this helps!

How to replace a digit in a string of numbers with a random number

I have a string which is a sequence of numbers between 0-9, I would like to replace some of the numbers in that string with random numbers, but I'm unable to do with with either rand or randi as I keep getting the following error:
Conversion to char from cell is not possible.
Error in work (line 58)
mut(i,7:14) = {mute_by};
Here's what I'm currently doing to try and alter some digits of my string:
% mutate probability 0.2
if (rand < 0.2)
% pick best chromosome to mutate
mut = combo{10};
mute_by = rand([0,9]);
for i = 1:5
mut(i) = {mute_by};
end
end
mut represents the string 110202132224154246176368198100
How would I go about doing this? I assumed it would be fairly simple but I've been going over the documentation for a while now and I can't find the solution.
What I would do is generate a logical array that represents true if you want to replace a particular position in your string and false otherwise. How you're determining this is by generating random floating pointing point numbers of the same size as your string, and checking to see if their values are < 0.2. For any positions in your string that satisfy this constraint, replace them with another random integer.
The best way to do this would be to convert your string into actual numbers so that you can actual modify their positions numerically, create our logical array, then replace these values with random integers at these co-ordinates.
Something like this:
rng(123); %// Set seed for reproducibility
mut = '110202132224154246176368198100';
mut_num = double(mut) - 48;
n = numel(mut_num);
vec = rand(1, n) < 0.4;
num_elem = sum(vec);
mut_num(vec) = randi(10,1,num_elem) - 1;
mut_final = char(mut_num + 48);
Let's go through this code slowly. rng is a random seed generator, and I set it to 123 so that you're able to reproduce the same results that I have made as random number generation... is of course random. I declare the number you have made as a string, then I have a nifty trick of turning each character in your string into a single element of a numeric array. I do this by casting to double, then subtracting by 48. By casting to double, each element gets converted into its ASCII code, and so 0 would be 48, 1 would be 49 and so on. Therefore, we need to subtract the values by 48 so that we can bring this down to a range of [0-9]. I then count how long your string is with numel, then figure out which values I want to replace by generating that logical vector we talked about.
We then count up how many elements we need to change, then generate a random integer vector that is exactly this size, and we use this logical vector to index into our recently converted string (being stored as a numeric array) with random integers. Note that randi generates values from 1 up to whatever maximum you want. Because this starts at 1, I have to generate up to 10, then subtract by 1. The output of randi gets placed into our numeric array, and then we convert our numeric array into a string with char. Note that we need to add by 48 to convert the numbers into their ASCII equivalents before creating our string.
I've changed the probability to 0.4 to actually see the changes better. Setting this to 0.2 I could barely notice any changes. mut_final would contain the changed string. Here is what they look like:
>> mut
mut =
110202132224154246176368198100
>> vec
vec =
Columns 1 through 13
0 1 1 0 0 0 0 0 0 1 1 0 0
Columns 14 through 26
1 1 0 1 1 0 0 0 0 0 0 0 1
Columns 27 through 30
1 1 1 0
>> mut_final
mut_final =
104202132444143248176368195610
vec contains those positions in the string you want to change, starting from the 2nd position, 3rd position, etc. The corresponding positions in mut change with respect to vec while the rest of the string is untouched and is finally stored in mut_final.

Matlab cells with Names

Note: Please if you can point a solution without 'eval', that would be great!!!
If not, I'll be thankful too :-)
Well, I have a cell (Var_s) that has in the first row strings and in the second row matrices:
clc
clearvars
fclose all
L=[11 22 33 44];
M=[1 2 3];
N=[101 102 103 104 105, 95 96 97 98 99];
Var_s=cell(2,3);
Var_s(1,1:3)={'Rn', 'LE', 'O'}; %// The strings are all different and were not created in a loop.
Var_s(2,1:3)={L, M, N}; %// No correlation is possible.
%//Than I delete all variables because I can work with the cell (Var_s{2,:})
%//to execute some computations
clearvars L M N
%//Now I want to save the values which are stored inside of the cells in the
%//second line of Var_s, Var_s{2,:}, associating to them the names in the first
%//row of the Var_s, Var_s{1,:}, in a .mat file
%//But let's imagine that instead of having size(Var_s{2,:})=3 I would have
%//something like 1000 (but lets keep it simple for now having just 3).
%//Consequently I want to use a 'for' to do this work!
%//And it is at this point that the issue appears. How can I use the strings
%//inside Var_s{1,:} to create variables and store them in the .mat file with
%//the values in the cells of Var_s{2,:} associated to them?
filename='Clima';
a=0;
save(filename,'a'); %//Creats the file with a variable a=0
for i=1:length(Var_s(2,:))
genvarname(Var_s{1,i})=Var_s{2,i}; %//The idea is to create a variable using a stringn and associate the values
save(filename,char(Var_s{1,i}),'-append'); %//The idea is to add the created variable that has the same name in Var_s{1,i}
end
clearvars
%//After all this I could access the variables that are stored in 'Clima.mat'
%//by their name such as
load('Clima.mat')
Rn
LE
O
And the result must be
Rn = 11 22 33 44
LE = 1 2 3
N = 101 102 103 104 105
Your question is pretty much fully covered in the docs to the save() command under "Save Structure Fields as Individual Variables". To get there, you only must create that struct.
To create that struct(), where you dynamically create its field names, not much of your code must be changed. Once your struct is created in that loop, just save the struct once after the loop with the option '-struct', which automatically then generates a new variable for each field in that struct.
s = struct();
for i=1:length(Var_s(2,:))
s.(Var_s{1,i})=Var_s{2,i}; % struct with dynamic field names
end
save(filename, '-struct', 's');
Now let's see, what we stored:
whos('-file', 'Clima.mat')
Name Size Bytes Class Attributes
LE 1x3 24 double
O 1x10 80 double
Rn 1x4 32 double
As you can see, we stored 3 variables in that file.

matlab string vector / array handling (multiplication u and str2num)

I would like to understand if this is really correct, or if this might be an issue in matlab.
I create an string vector/array via:
>>a=['1','2';'3','4']
It returns:
a =
12
34
Now I would like to convert the content from string to number and multiply this with a number:
>>6*str2num(a)
The result looks like this:
a =
72
204
I don't understand why the comma separated elements (strings) will be concatenated and not separated handled. If you use number instead of strings they will be separated handled. Then it looks like this:
>> a=[1,2;3,4]
a =
1 2
3 4
>> 6*a
ans =
6 12
18 24
I would expect the same results. Any ideas ?
Thanks
Have you read about how string handling is done in MATLAB?
Basically, multiple strings can only be stored as a column vector (of strings). If attempted to store as a row vector, they will be concatenated. This is why strings '1' and '2' are being concatenated, as well as '3' and '4'. Also note, that this is only possible if all resulting strings are of the same length.
I'm not sure what you're trying to do, but if you want to store strings as a matrix (that is, multiple strings in a row), consider storing them in a cell array, for instance:
>> A = {'1', '2'; '3', '4'}
A =
'1' '2'
'3' '4'
>> cellfun(#str2num, A)
ans =
1 2
3 4
I would say that using a cell array as #EitanT suggests would probably be the best solution for you.
However, it is possible to handle strings (or rather characters) like the way you tried by manually inserting spaces and lining up the number of characters.
For example
>> a=['1 2';'3 4']
produces
a =
1 2
3 4
and using
>> 6*str2num(a)
produces
ans =
6 12
18 24
Converting between a matrix and a string using
b=[1,2;3,10000];
num2str(b)
spaces are inserted automatically and the characters are lined up properly. This produces
ans =
1 2
3 10000

Resources