Inserting items in an array every nth place in octave / matlab - arrays

How can I insert elements in an array (a2) every nth place in (a1)
Example: Logic
a1 = [1,10,2,20,3,30,4,40,5,50];
a2 = [100,200,300,400,500];
n=3 % n would be the position to place the elements found in (a2) every **nth** position in (a1).
*n is the starting position at which the array a2 is inserted into a1*
The new a1 if n=3 after inserting a2 into it would look like
a1 = [1,10,100,2,20,200,3,30,300,4,40,400,5,50,500];
The new a1 if n=2 after inserting a2 into it would look like
a1 = [1,100,10,2,200,20,3,300,30,4,400,40,5,500,50];
The new a1 if n=1 after inserting a2 into it would look like
a1 = [100,1,10,200,2,20,300,3,30,400,4,40,500,5,50];
I tried
a1(1:3:end,:) = a2;
but I get dimensions mismatch error.
Please note this is just an example so I can't just calculate an answer I need to insert the data into the array. n is the starting position at which the array a2 is inserted into a1

First allocate an array of the combined size, then insert both original arrays to required indices. With a2 it is easy, you can just use n:n:end. To get indices for a1 you can subtract the set of a2 indices from the set of all indices:
a1 = [1,10,2,20,3,30,4,40,5,50];
a2 = [100,200,300,400,500];
n = 3;
res = zeros(1,length(a1)+length(a2));
res(n:n:n*length(a2)) = a2;
a1Ind = setdiff(1:length(res), n:n:n*length(a2));
res(a1Ind) = a1;
>> res
res =
1 10 100 2 20 200 3 30 300 4 40 400 5 50 500

Another option is to use circshift to shift the row you want on top
orig_array=[1:5;10:10:50;100:100:500;1000:1000:5000];
row_on_top=3 %row to be on top
[a1_rows a1_cols]=size(orig_array)
a1 = circshift(orig_array, [-mod(row_on_top,a1_rows)+1, 0])
Anew = zeros(1,a1_rows*a1_cols)
for n=1:1:a1_rows
n
insert_idx=[n:a1_rows:a1_cols*a1_rows] %create insert idx
Anew(insert_idx(1:a1_cols))=a1(n,:) %insert only 1:a1_cols values
end
Anew=Anew(:)

Related

Loading arrays of different sizes into a single array

I have 100 arrays with the dimension of nx1. n varies from one array to the next (e.g, n1 = 50, n2 = 52, n3 = 48 etc.). I would like to combine all these arrays into a single one with the dimension of 100 x m with m being the max of n's.
The issue I am running into is that as n varies, Matlab will throw out an error says that the dimensions mismatch. Is there a way to get around this so I can pad "missing" cell with N/A? For instance, if the first array contains 50 elements (i.e., n1 = 50) like this:
23
31
6
...
22
the second array contains 52 elements (i.e., n2 = 52) like this:
25
85
41
...
8
12
66
The result should be:
23 25
31 85
6 41
... ...
22 8
N/A 12
N/A 66
Thanks to the community in advance!
Here is another approach without eval.
array_lengths = cellfun(#numel, arrays);
max_length = max(array_lengths);
result = nan(max_rows, num_arrays);
for r=1:num_arrays
result(1:array_lengths(r),r) = arrays{r}(1:array_lengths(r));
end
Some explanation: I'm assuming your arrays are stored in a cell to begin with. Here is some code to generate fictitious data with the dimensions you gave:
% some dummy data for your arrays.
num_arrays = 100;
primerArrayCell = num2cell(ones(1,num_arrays)); % , 1, ones(1, num_arrays));
arrays = cellfun(#(c) rand(randi(50, 1),1), primerArrayCell, 'uniformoutput',false);
You can use cellfun with an anonymous function to get the lengths of each individual array:
% Assume your arrays are in a cell of arrays with the variable name arrays
array_lengths = cellfun(#numel, arrays);
max_length = max(array_lengths);
Allocate an array of nan values to store your result
% initialize your data to nan's.
result = nan(max_rows, num_arrays);
Then fill in the non-nan values based on the length of the arrays calculated previously.
for r=1:num_arrays
result(1:array_lengths(r),r) = arrays{r}(1:array_lengths(r));
end
You may want to consider using structure arrays for storing such datasets as it makes everything easier when merging them into a single array.
But to answer your question, if you have arrays like this:
a1 = 1:20; % array of size 1 x 20
n1 = numel(a1); % 20
a2 = 50:60; % array of size 1 x 11
n2 = numel(a2); % 11
... say you have nArrs arrays
Given nArrs arrays for example, you can create the desired matrix res like this:
m = max([n1, n2, .... ]);
res = ones(m,nArrs) * nan; % initialize the result matrix w/ nan
% Manually
res(1:n1,1) = a1.';
res(1:n2,2) = a2.';
% ... so on
% Or use eval instead like this
for i = 1:nArrs
eval(['res(1:n' int2str(i) ', i) = a' int2str(i) '.'';'])
end
Now bear in mind that using eval is NOT recommended but hopefully that just gives you an idea as to what to do. If you did use structures, you can replace eval with something more efficient and robust like arrayfun for instance.

reversing shuffling of array by indexing

I have a matrix whose columns which was shuffled according to some index. I know want to find the index that 'unshuffles' the array back into its original state.
For example:
myArray = [10 20 30 40 50 60]';
myShuffledArray = nan(6,3)
myShufflingIndex = nan(6,3)
for x = 1:3
myShufflingIndex(:,x) = randperm(length(myArray))';
myShuffledArray(:,x) = myArray(myShufflingIndex(:,x));
end
Now I want to find a matrix myUnshufflingIndex, which reverses the shuffling to get an array myUnshuffledArray = [10 20 30 40 50 60; 10 20 30 40 50 60; 10 20 30 40 50 60]'
I expect to use myUnshufflingIndex in the following way:
for x = 1:3
myUnShuffledArray(:,x) = myShuffledArray(myUnshufflingIndex(:,x), x);
end
For example, if one column in myShufflingIndex = [2 4 6 3 5 1]', then the corresponding column in myUnshufflingIndex is [6 1 4 2 5 3]'
Any ideas on how to get myUnshufflingIndex in a neat vectorised way? Also, is there a better way to unshuffle the array columnwise than in a loop?
You can get myUnshufflingIndex with a single call to sort:
[~, myUnshufflingIndex] = sort(myShufflingIndex, 1);
Alternatively, you don't even need to compute myUnshufflingIndex, since you can just use myShufflingIndex on the left hand side of the assignment to unshuffle the data:
for x = 1:3
myUnShuffledArray(myShufflingIndex(:, x), x) = myShuffledArray(:, x);
end
And if you'd like to avoid a for loop while unshuffling, you can vectorize it by adding an offset to each column of your index, turning it into a matrix of linear indices instead of just row indices:
[nRows, nCols] = size(myShufflingIndex);
myUnshufflingIndex = myShufflingIndex+repmat(0:nRows:(nRows*(nCols-1)), nRows, 1);
myUnShuffledArray = nan(nRows, nCols); % Preallocate
myUnShuffledArray(myUnshufflingIndex) = myShuffledArray;

Finding location of elements w.r.t original matrix after reshape in Matlab

I have a 1*262144 matrix which I have reshaped into a 512*512 matrix. Now, I need certain elements from my 2nd matrix and want to know their location as it was in the original row matrix. Say, i need element which is at (256,4) in my reshaped matrix. How can I know the position of this element in my original row only matrix?
matri_working_now = C(1,:);
matrix_working_now = reshape(matri_working_now,512,512);
[nrows,ncols] = size(matrix_stables); %matrix_stables is a matrix over which I am looping over which contains the locations of the desired elements as per the reshaped matrix. this itself is a 30839*2 matrix
for row = 1:nrows
for col = 1:ncols
%sub2ind(size(matrix_working_now),row,col)
%fprintf('iteration is equal to %6.2f.\n',row,col);
[rowss colum] = ind2sub(size(matri_working_now),sub2ind(size(matrix_working_now),matrix_stable(row),matrix_stable(col))); % i am accessing the elements of matrix_stables which provide me the row and column numbers;
end
end
Any suggestions/ideas?
Thanks!
Since your original matrix is a vector, you only need to convert from subindices to linear index, with sub2ind:
col = sub2ind(size(reshapedMatrix), 256,4);
In general, if the original matrix is not necessarily a vector, you need a second step with ind2sub:
[row col] = ind2sub(size(originalMatrix), sub2ind(size(reshapedMatrix), 256,4));
Example:
>> originalMatrix = (1:10).^2
originalMatrix =
1 4 9 16 25 36 49 64 81 100
>> reshapedMatrix = reshape(originalMatrix, 2,5)
reshapedMatrix =
1 9 25 49 81
4 16 36 64 100
>> reshapedMatrix(2,3)
ans =
36
>> [row col] = ind2sub(size(originalMatrix), sub2ind(size(reshapedMatrix), 2,3))
row =
1
col =
6
>> originalMatrix(row,col)
ans =
36

Select range based on contents of an array

I have two arrays. I'd like to copy ranges of data from one of them, based on a list of array locations stored in the other. For example, if the first array were comprised of 100 rows and 2 columns, I might like to copy rows 10-20, rows 60-70 and rows 75-79. If that were the case, then the contents of the second array would be as follows:
b =
10 20
60 70
75 79
In order to select the appropriate rows of the first array based on the second (let's call it 'a'), I would do the following:
b = [a(1,1):a(1,2) a(2,1):a(2,2) a(3,1):a(3,2)]
This works, and returns array 'b' which is basically array 'a' with the correct contents extracted.
The problem is, array 'b' actually contains between 50 and 60 rows (i.e ranges to be included).
How do I make the above code more efficient, such that it works for any number of rows in 'b'?
Example:
a = rand(100,1);
ranges = [
10 20
60 70
75 79
];
idx = arrayfun(#colon, ranges(:,1), ranges(:,2), 'Uniform',false);
idx = [idx{:}];
b = a(idx)
You could use a for, assuming ranges of values to be extracted from a are in b, and should go to c:
% input
a = rand(100,2);
b = [10 20; 60 70; 75 79];
% output
c = zeros(1,2);
for i = 1:size(b,1)
c = vertcat(c a(b(i,1):b(i,2), :));
end
c = c(2:size(c,1), :);
A solution using cellfun and cell arrays:
% Some example data:
a = reshape(1:100, 10, 10);
b = [ 2 3; 5 8; 10 10 ];
Here's the code:
bCell = mat2cell(b, 3, [ 1 1 ]);
aRows = cell2mat(arrayfun(#(x,y) a(x:y, :), bCell{1}, bCell{2}, 'UniformOutput', false));

Comparing two string array and returning the differences of each in vb6 with a good performance

I got 2 expandable arrays with strings in them and I want to compare both with each other to see which includes strings that the other dont.
lets say my arrays are like:
ARRAY - 1 ARRAY - 2
a1 a1
a2 a2
a3 a3
a9 a4
a10 a8
a11 a10
a12 a11
i wanna get the result as:
ARRAY - 4 ARRAY - 5 ARRAY - 6
a9 a4 a1
a12 a8 a2
a3
a10
a11
another 3 different array should give me the difference of array1 when compared to array 2
-array4 here gives the strings that is included in array1 but not found in array2
-array5 here gives the strings that is included in array2 but not found in array1
-array6 here gives the strings that is found in both
for this i ve coded:
i = 0
j = 0
For Each innerElement1 In CompareElement1 'CompareElement1 is the array1 here
NoneFound = 1
'Ones thats in first element also found in second element..
For Each innerElement2 In CompareElement2 'CompareElement2 is the array2 here
If innerElement1 = innerElement2 Then
'Expand array
ReDim Preserve IncludedInBoth(0 To UBound(IncludedInBoth) + 1)
IncludedInBoth(i) = innerElement1
'Item found in both so NoneFound is 0.
NoneFound = 0
i = i + 1
End If
Next
'Ones thats in first element but not found in second element..
If NoneFound = 1 Then
'Expand array
ReDim Preserve NotIncludedInElem2(0 To UBound(NotIncludedInElem2) + 1)
NotIncludedInElem2(j) = innerElement1
j = j + 1
End If
Next
'Seperate Comparison for the ones that found in second element _
but not found in first element..
i = 0
For Each innerElement1 In CompareElement2
NoneFound = 1
'Ones thats in second element also found in first element.
For Each innerElement2 In IncludedInBoth
If innerElement1 = innerElement2 Then
'Item found in both so NoneFound is 0.
NoneFound = 0
End If
Next
'Ones thats in second element but not found in first element..
If NoneFound = 1 Then
'Expand array
ReDim Preserve NotIncludedInElem1(0 To UBound(NotIncludedInElem1) + 1)
NotIncludedInElem1(i) = innerElement1
i = i + 1
End If
Next
my code up there exactly does the comparing and giving the true answer but with a lack of performance caused by inner for each calls is there a way to do this comparing with a faster way? its taking like forever to finish this comparing..
also a little note:
array1 and array2 are two different sized arrays that contains thousands(~100.000)of strings in each.
also they are not in order. i would like to learn how to order them alphabetically.
with that amount of data, create a database, load to tables and use SQL. It will run too slow trying to do it manually.

Resources