I have two giant array which looks like:
A = [11, 11, 12, 3, 3, 4, 4, 4 ];
B = [ 12, 4; 3, 11; 11, 1; 4, 13 ];
I want to create an array which takes values from B and column 1 from A to look like:
C = [ 11, 1; 11, 1; 12, 4; 3, 11; 3, 11; 4, 13; 4, 13; 4, 13 ];
I don't want to use for or any other kind of loop to optimize the process.
Sorry for being terse.
I will search each element from column 1 of A in column 1 of B and pick the corresponding column 2 elements from B and create a new array with column 1 elements of A and discovered column 2 elements from B.
What you are doing in this problem is using A and searching the first column of B to see if there's a match. Once there's a match, extract out the row that corresponds to this matched location in B. Repeat this for the rest of the values in A.
Assuming that all values of A can be found in B and that the first column of B is distinct and that there are no duplicates, you can a unique call and sortrows call. The unique call is on A so that you can assign each value in A to be a unique label in sorted order. You would then use these labels to index into the sorted version of B to get your desired result:
[~,~,id] = unique(A);
Bs = sortrows(B);
C = Bs(id,:);
We get for C:
C =
11 1
11 1
12 4
3 11
3 11
4 13
4 13
4 13
Thanks to #rayryeng for clarifying the question to me.
Assuming each element from A is present in column 1 of B:
[~, ind] = max(bsxfun(#eq, A(:).', B(:,1)), [], 1);
C = B(ind,:);
If that assumption doesn't necessarily hold:
[val, ind] = max(bsxfun(#eq, A(:).', B(:,1)), [], 1);
C = B(ind(val),:);
So for example A = [11, 20, 12, 3, 3, 4, 4, 4 ]; would produce
C =
11 1
12 4
3 11
3 11
4 13
4 13
4 13
Related
I wonder if there is a way of looping through a number of arrays of different sizes and trimming data from the beginning of each array in order to achieve the same amount of elements in each array?
For instance, if I have:
A = [4 3 9 8 13]
B = [15 2 6 11 1 12 8 9 10 13 4]
C = [2 3 11 12 10 9 15 4 14]
and I want B an C to lose some elements at the beginning, such that they end up being 5 elements in length, just like A, to achieve:
A = [4 3 9 8 13]
B = [8 9 10 13 4]
C = [10 9 15 4 14]
How would I do that?
EDIT/UPDATE:
I have accepted the answer proposed by #excaza, who wrote a nice function called "naivetrim". I saved that function as a .m script and then used it: First I define my three arrays and, as #excaza suggests, called the function:
[A, B, C] = naivetrim(A, B, C);
Another solution variation that worked for me - based on #Sardar_Usama's answer below (looping it). I liked this as well, because it was a bit more straightforward (with my level, I can follow what is happening in the code)
A = [4 3 9 8 13]
B = [15 2 6 11 1 12 8 9 10 13 4]
C = [2 3 11 12 10 9 15 4 14]
arrays = {A,B,C}
temp = min([numel(A),numel(B), numel(C)]); %finding the minimum number of elements
% Storing only required elements
for i = 1:size(arrays,2)
currentarray = arrays{i}
arrays(i) = {currentarray(end-temp+1:end)}
end
A naive looped solution:
function testcode()
% Sample data arrays
A = [4, 3, 9, 8, 13];
B = [15, 2, 6, 11, 1, 12, 8, 9, 10, 13, 4];
C = [2, 3, 11, 12, 10, 9, 15, 4, 14];
[A, B, C] = naivetrim(A, B, C);
end
function varargout = naivetrim(varargin)
% Assumes all inputs are vectors
% Find minumum length
lengths = zeros(1, length(varargin), 'uint32'); % Preallocate
for ii = 1:length(varargin)
lengths(ii) = length(varargin{ii});
end
% Loop through input arrays and trim any that are longer than the shortest
% input vector
minlength = min(lengths);
varargout = cell(size(varargin)); % Preallocate
for ii = 1:length(varargout)
if length(varargin{ii}) >= minlength
varargout{ii} = varargin{ii}(end-minlength+1:end);
end
end
end
Which returns:
A =
4 3 9 8 13
B =
8 9 10 13 4
C =
10 9 15 4 14
If you have a large number of arrays you may be better off with alternative intermediate storage data types, like cells or structures, which would be "simpler" to assign and iterate through.
Timing code for a few different similar approaches can be found in this Gist.
Performance Profile, MATLAB (R2016b)
Number of Elements in A: 999999
Number of Elements in B: 424242
Number of Elements in C: 101325
Trimming, deletion: 0.012537 s
Trimming, copying: 0.000430 s
Trimming, cellfun copying: 0.000493 s
If there are not many matrices then it can be done as:
temp = min([numel(A),numel(B), numel(C)]); %finding the minimum number of elements
% Storing only required elements
A = A(end-temp+1:end);
B = B(end-temp+1:end);
C = C(end-temp+1:end);
Since I am quite new with Swift, I was reading about Subscripts in Swift. It gave this example under Subscript Options: theExample
My question is how is the formula, grid[(row * columns) + column], is suppose to correspond to the right value in the grid array because when I calculate it it corresponds to the wrong value. Somebody please help.
0 1 2 3 4
--------------------
0 | 0, 1, 2, 3, 4,
1 | 5, 6, 7, 8, 9,
2 | 10, 11, 12, 13, 14
You have columns = 5.
If you want to get 8, row = 1 and column = 3.
row * columns + column
1 * 5 + 3 = 8.
I have the following sample sheet:
1/A B C D E F G H I J
2
3 Points 8 4 2 1
4
5 Values 1 2 3 4 4 3 1 2
I'm trying to sum the 'Points' based upon the array index from the 'Values'.
My expected result from this is: 30
Here is my formula:
{=SUM(INDEX($C$3:$F$3,1,C5:J5))}
For some reason though, this only returns the first value of the array, rather than the entire sum.
To clarify, the C# version would be something like:
var points = new int[] { 8, 4, 2, 1 };
var values = new int[] { 2, 4, 3, 1, 2, 4, 2 };
var result = (from v in values
select points[v - 1]).Sum(); // -1 as '4' will crash, but in Excel '4' is fine
Edit: Adding further clarifying example
Another example to clarify:
Points is the array. The 'values' represents the index of the array to sum.
The example above is the same as:
=SUM(8, 4, 2, 1, 1, 2, 8, 4)
INDEX will never take its row or column parameters from arrays and then perform multiple times within one array formula contained in one cell. For this OFFSET will be needed.
Either
{=SUM(N(OFFSET($C$3,,C5:J5-1)))}
as an array formula.
Or
=SUMPRODUCT(N(OFFSET($C$3,,C5:J5-1)))
as an implicit array formula without the need for [Ctrl]+[Shift]+[Enter].
I would like to access the lower triangular part of a (square) table with cell elements. I tried the tril function, but it doesn't work for input arguments of type 'cell'. Is there any workaround? Thanks.
Is this what you want?
c = {1, [2 3], 4; [5 6 7], [8 9], 10; 11, 12, [13 14]}; %// example 3x3 cell array
mask = tril(true(size(c,1), size(c,2))); %// creat mask
result = c(mask); %// index cell array with mask
This produces a column cell array with the selected cells in column-major order:
result{1} =
1
result{2} =
5 6 7
result{3} =
11
result{4} =
8 9
result{5} =
12
result{6} =
13 14
MATLAB:
In MATLAB,
I have 2 m-by-n matrices, A and B. I want to make a set of n
m-by-2 matrices such as in ith matrix (of set of n), first column will be ith
column from A and second column will be ith column from B.
How to extract and concatenate ith columns from both matrices?
How I can store these n matrices? Using loops? (Memory?)
Example:
Input:
A = [ 1, 2, 3; 4, 5 ,6; 7, 8, 9] (3x3 matrix)
B = [ 11, 22, 33; 44, 55 ,66; 77, 88, 99] (3x3 matrix)
Output:
For i=1:3
C1 = [1, 11; 4, 44; 7, 77]
C2 = [2, 22; 5, 55; 8, 88]
C3 = [3, 33; 6, 66; 9, 99]
The first thing I'm going to do is change your variable names. Mainly this is just to make referring to the variables easier, especially as m and n change. Instead of writing
C1(:,:)
C2(:,:)
...
Cn(:,:)
I'm going to write
C(:,:,1)
C(:,:,2)
...
C(:,:,n)
All I've done is moved the index from the variable name to the index of the 3rd dimension.
Now, to create the C array:
A = [ 1, 2, 3; 4, 5 ,6; 7, 8, 9]
B = [ 11, 22, 33; 44, 55 ,66; 77, 88, 99]
[m,n]=size(A)
C = reshape([A',B']', m, 2, n)
The output of this is:
A =
1 2 3
4 5 6
7 8 9
B =
11 22 33
44 55 66
77 88 99
m = 3
n = 3
C =
ans(:,:,1) =
1 11
4 44
7 77
ans(:,:,2) =
2 22
5 55
8 88
ans(:,:,3) =
3 33
6 66
9 99
As you can see, C(:,:,1) is equal to C1 in your example, C(:,:,2) = C2 and so on. And this extends without change as the sizes of A and B change. You never have to come up with new variable names. And all you have to do to know how many m-by-2 matrices you've got is
numVars = size(C,3);
Note: This uses the same technique found in the answer here: matlab - how to merge/interlace 2 matrices?