Define multiple variables at the same time in MATLAB - arrays

I want to define multiple variables at the same time.
For example, I want to define
a = 1
b = 2
c = 3
like this.
So I made a matrix with [a,b,c]:
x = [a, b, c];
y = [1, 2, 3];
x = y
So I want to get the following answer.
a = 1
b = 2
c = 3
If I use
[a, b, c] = deal(1, 2, 3)
then, I can get
a = 1
b = 2
c = 3
But I want to use matrix x instead of [a, b, c]
So if I use,
x = deal(1,2,3)
there is an error.
Is there any solution?

Maybe I don't understand the question but if you want to use the matrix x instead of [a, b, c] why don't you just define it as
x = [1, 2, 3];
From your question it sounds to me as if you are overcomplicating the problem. You begin by wanting to declare
a = 1;
b = 2;
c = 3;
but what you want instead according to the end of your question is
x = [1, 2, 3];
If you define x as above you can the refer to the individual elements of x like
>> x(1), x(2), x(3)
ans =
1
ans =
2
ans =
3
Now you have the best of both worlds with 1 definition. You can refer to a, b and c using x(1), x(2), x(3) instead and you've only had to define x once with x = [1, 2, 3];.

You cannot deal into a numeric array, but you can deal into a cell array and then concatenate all the elements in the cell array, like this:
[x{1:3}] = deal(1, 2, 3); % x is a cell array {1, 2, 3}
x = [x{:}]; % x is now a numeric array [1, 2, 3]

Related

Matlab diff command with bigger step

The command diff calculates differences between two consecutive elements. Is there any way to calculates differences between two nonconsecutive elements?
For example, with
x = [1,2,3,4,5,6]
is there any command to find
[x(3)-x(1),x(4)-x(2),x(5)-x(3),x(6)-x(4)] = [2,2,2,2]
or
[x(4)-x(1),x(5)-x(2),x(6)-x(3)] = [3,3,3]
And in general, for the case of a matrix? I can write some code for this; I just wonder if there any existing command in Matlab for this?
An example of the matrix case
x = [1,2,3,4;1,3,5,7;2,4,6,8]
and we want to find
[x(1,3)-x(1,1),x(1,4)-x(1,2);x(2,3)-x(2,1),x(2,4)-x(2,2);x(3,3)-x(3,1),x(3,4)-x(3,2)] = [2,2;4,4;4,4]
For vectors
I would use convolution with kernel [1 0 ยทยทยท 0 -1], where the number of zeros depends on the desired step. This can be done with function conv:
x = [1,2,3,4,5,6]; % data
s = 2; % step
result = conv(x, [1 zeros(1,s-1) -1], 'valid');
gives
result =
2 2 2 2
For matrices or N-dimensional arrays
The above can be generalized using convn, with a kernel defined as before but oriented along the desired dimension:
x = [1,2,3,4; 1,3,5,7; 2,4,6,8]; % data
s = 2; % step
d = 2; % dimension
result = convn(x, reshape(([1 zeros(1,s-1) -1]), [ones(1,d-1) s+1 1]), 'valid');
gives
result =
2 2
4 4
4 4
I'm not aware of such a function, but you can simply set up a very simple anonymous function
stepDiff = #(x, s) x(:, s:end)-x(:, 1:end-s+1);
Will give outputs like:
x = [1, 2, 3, 4, 5, 6];
>> stepDiff(x, 2)
ans =
1 1 1 1 1
>> stepDiff(x, 4)
ans =
3 3 3
x = [1, 2, 3, 4; 1, 3, 5, 7; 2, 4, 6, 8];
>> stepDiff(x, 3)
ans =
2 2
4 4
4 4

Numpy: Comparing array elements within another array

I have a numpy array
X = [[1,2], [3,4], [5,6], [1,2], [5,6]]
I want a numpy array Y = [1, 2, 3, 1, 3], where [1,2] is replaced by 1, [3,4] replaced by 2 and so on. This is for a very large (think millions) X.
Intuition is Y[X == [1,2]] = 1. But this does't work.
Intuition is Y[X == [1,2]] = 1. But this does't work.
Here is how to make it work:
Y = np.empty(len(X), dtype=np.int)
Y[np.all(X == [1, 2], 1)] = 1
To process all the possible values:
s = set(map(tuple, X))
r = np.arange(1, len(s) + 1) # or assign whatever values you want
cond = [np.all(X == v, 1) for v in s]
Y = np.dot(r, cond)

Filter out combinations in Matlab

Currently I can generate all the combinations from categories alpha, beta, gamma and delta (1 1 1 1, 1 1 1 2 etc.).
Current code:
alpha = [1, 2, 3];
beta = [1, 2, 3, 4, 5];
gamma = [1, 2, 3, 4, 5];
delta = [1, 2, 3];
[a, b, c, d] = ndgrid (alpha, beta, gamma, delta);
combination = [a(:), b(:), c(:), d(:)];
I want to filter out some of those combinations i.e. get rid of any of the combinations where alpha is 1 and gamma is 4 etc.
How would I approach this?
What you're looking for is logical indexing
c1 = (combination(:,1) ~= 1); %rows where alpha is not 1
c2 = (combination(:,3) ~= 4); %rows where gamma is not 4
desired = combination(c1&c2,:); %output rows where both c1 and c2 are true
Ian Riley's answer has provided the correct approach if you want to create a new array from that information. Just adding to his answer that you can also use the same approach to remove the unwanted rows directly, by setting them to empty, i.e.:
>> combination(combination(:,1) == 1,:) = [];
>> combination(combination(:,3) == 4,:) = [];

How to swap two row vectors inside a row vector?

i am trying to swap 2 row vectors which are inside a row vector.
For example:
a=[1 2 3];
b=[5 3];
c=[9 3 7 6];
d=[7 5];
X1= [ a, b , d, c ];
I want to do random swapping such that two of the a,b,c,d remains at the same position in X1 and the remaining two of them shuffles in X1. For example, some of the possible random swaps are:
[b,a,d,c] % a and b swap with each other whereas d and c remain at the same place
[d,b,a,c] % a and d swap with each other whereas b and c remain at the same place
[c,b,d,a] % a and c swap with each other whereas b and d remain at the same place
.....
.....
The proper and safe way to what you're trying to do is by assigning your variables to a cell, permuting the elements of the cell, and finally concatenating the result.
Imagine a specific permutation, say, [c, b, a, d]. This permutation can be coded as [3, 2, 1, 4] in terms of a mapping. The corresponding code to generate your array is then:
% generate input
a = [1, 2, 3];
b = [5, 3];
c = [9, 3, 7, 6];
d = [7, 5];
% generate cell to permute
tmpcell = {a, b, c, d};
% define our permutation
permnow = [3, 2, 1, 4];
% permute and concatenate the result into an array
result = [tmpcell{permnow}];
% check if this is indeed OK:
disp(isequal(result,[c, b, a, d])) % should print 1
The only thing you might still need is to generate a random configuration. This is easy: you just have to choose 2 random indices and swap them in [1, 2, 3, 4]. A lazy option to do this:
nvars = length(tmpcell); % generalizes to multiple variables this way
idperm = 1:nvars;
i1 = randi(nvars,1);
partperm = setdiff(idperm, i1); % vector of remaining indices, avoid duplication
i2 = partperm(randi(nvars-1,1)); % second index, guaranteed distinct from i1
permnow = idperm;
permnow([i1, i2]) = [i2, i1]; % swap the two indices

How to add values of arrays having different lengths [duplicate]

This question already has answers here:
Sum of arrays of different size [closed]
(4 answers)
Closed 6 years ago.
I want to add values of two different length array.
a =[1,2,3]
b= [1,2]
c = [1,2,3,4]
and so on..
I want result to be like [3,6,6,4]. How to do this in ruby on rails.
In order to make it dynamic, I would create arrays of array with your a, b, c =>
a = [1, 2, 3]
b = [1, 2]
c = [1, 2, 3, 4]
arrays = [a, b, c]
Then I would retrieve the max size :
max_size = arrays.map(&:size).max #=> 4
Then the following line would give you your answer :
max_size.times.map{ |i| arrays.reduce(0){|s, a| s + a.fetch(i, 0)}} #=> [3, 6, 6, 4]
You can build a new array that consists of all those array, and then can write the following code to get the array that has combined entries of each array:
a = [1,2,3]
b = [1,2,3]
c = [1,2,3,4]
Before you apply the rest of the code, you need to make sure that each array has the same length. For that, you can append 0 in all the arrays if need be, to ensure that each array has the same length as the rest of the arrays have.
a = [1,2,3,0]
b = [1,2,3,0]
c = [1,2,3,4]
combined_array = [a,b,c]
result = combined_array.transpose.map { |a| a.reduce :+ }
Extending the answer from #Arslan Ali
I added a way to make all the arrays the same size, so that his method of summing can be applied:
a = [1,2,3]
b = [1,2,3]
c = [1,2,3,4]
arrays = [a, b, c]
size = [a, b, c].map{|a| a.size}.max # Compute maximum size
combined_array = [a,b,c].map{|a| a.fill(a.size...size){0}} # Fill arrays to maximum size
result = combined_array.transpose.map { |a| a.reduce :+ } # Sum everything
Here's one way:
a = [1, 2, 3]
b = [1, 2, 3]
c = [1, 2, 3, 4]
[a,b,c].inject([]) do |totals, add|
add.each_with_index do |n, i|
totals[i] = (totals[i] || 0) + n
end
totals
end

Resources