how to pick up all combination of numbers from multiple vectors

조회 수: 104 (최근 30일)
mohamed Faraj
mohamed Faraj 2019년 8월 13일
편집: Bruno Luong 2024년 3월 25일 14:02
I have a number of vectors, probably with different lengths, e.g., a=[1 2 3], b=[4 5 6 7] and c=[8 9 10 11 12]. From a, b and c I have 3*4*5=60 possible points, e.g., one possibility is (1,4,8). If I know the number of vectors and the length of each vector in advance, this is easy to program. However, I want to write a general code that can find all these combinations regardless of the number of vectors and their individual lengths
  댓글 수: 2
dpb
dpb 2019년 8월 13일
The problem is using named variables instead cell array or struct with named fields or somesuch.
If do that, you can simply catenate the vectors programmatically with no problem. Of course, you can easily run into memory problems here in that the number grows geometrically.

댓글을 달려면 로그인하십시오.

채택된 답변

John D'Errico
John D'Errico 2019년 8월 13일
Don't store your vectors separately. Instead, learn to use tools like cell arrays, which make things hugely more efficient.
V = {[1 2 3],[4 5 6 7],[8 9 10 11 12]};
Next, how do you use a cell array for this purpose? You pass the elements into ndgrid, using what is called acomma separated list. (Or meshgrid.) That is what you get when you type V{:}, a comma separated list. It allows you to pass in each element of the cell array into a function as if each element of the cell array was an argument of the function.
For example, if we did this:
[G1,G2,G3] = ndgrid(V{:});
Hmm. That creates three different arrays, that do contain all combinations of the elements of those vectors if you look carefully. But here we don't want to split the results into n different named arrays. We want a cell array as output. So now, try this:
C = cell(1,numel(V));
[C{:}] = ndgrid(V{:})
C =
1×3 cell array
{3×4×5 double} {3×4×5 double} {3×4×5 double}
Better. We have captured the output from ndgrid back into a cell array. But what we probably wanted was one flat array, with three columns, and here, 60 rows. We could convert each of those arrays into a column vector easily enough.
C = cellfun(@(X) reshape(X,[],1),C,'UniformOutput',false)
C =
1×3 cell array
{60×1 double} {60×1 double} {60×1 double}
And, now finally, just convert C into a flat array, using a tool like horzcat. (square brackets will suffice. That is...
C = horzcat(C{:})
C =
1 4 8
2 4 8
3 4 8
1 5 8
2 5 8
3 5 8
1 6 8
2 6 8
3 6 8
1 7 8
2 7 8
3 7 8
1 4 9
2 4 9
3 4 9
1 5 9
...
2 7 12
3 7 12
As you should see, nothing I did was dependent on the size of the arrays, the length of the vectors, the number of different vectors. That was all driven by the one initial cell array as I created it. Learn to use MATLAB, as it was designed to be used.
  댓글 수: 3
Afrad Patan
Afrad Patan 2021년 7월 22일
Hi john, in the same way i need to generate combinations for large number of array elements like If A=1:15, B=1:17, C=1:10, D=1:4, .....X=1:9, Y=1:13 and final array like Z={A,B,C,.....X,Y}. from your solution iam getting out of memory (requesting 107.3 GB for your large no.of array elements, this may slow your matlab unresponsive) error, what can i do here?i have 16gb internal memory in my pc still i need large amount of memory.
진환 유
진환 유 2022년 3월 16일
it was really helpful for me. Thank you for good solution!

댓글을 달려면 로그인하십시오.

추가 답변 (3개)

Adam Danz
Adam Danz 2019년 8월 13일
편집: Adam Danz 2023년 4월 4일
Here are two solutions for before/after R2023a.
Use combinations in MATLAB R2023a or later
% Demo data
a = 1:3;
b = 11:13;
c = -4:1;
d = 9;
allCombinations = combinations(a,b,c,d)
allCombinations = 54×4 table
a b c d _ __ __ _ 1 11 -4 9 1 11 -3 9 1 11 -2 9 1 11 -1 9 1 11 0 9 1 11 1 9 1 12 -4 9 1 12 -3 9 1 12 -2 9 1 12 -1 9 1 12 0 9 1 12 1 9 1 13 -4 9 1 13 -3 9 1 13 -2 9 1 13 -1 9
Before R2023a
This solution places all vectors in a cell array and uses ndgrid to create permutations. See comments for more detail. T
% Use the same demo data created above.
% Put all vectors into cell array
allVecs = {a,b,c,d};
sub = cell(1,numel(allVecs));
[sub{:}] = ndgrid(allVecs{:});
sub = cellfun(@(x)x(:),sub,'UniformOutput', false);
% allPerms is [m x n] matrix of m permutations of n vectors
% m should equal prod(cellfun(@numel,allVecs))
% n should equal numel(allVecs)
allPerms = cell2mat(sub)
allPerms = 54×4
1 11 -4 9 2 11 -4 9 3 11 -4 9 1 12 -4 9 2 12 -4 9 3 12 -4 9 1 13 -4 9 2 13 -4 9 3 13 -4 9 1 11 -3 9
Compare results
combinations() produces a table and my second solution produces a matrix with rows in a different order. Here I'll resort the rows of the table to match the rows of the matrix and we'll confirm that the two solutions are equal.
allCombinationsMat = sortrows(allCombinations{:,:},[4 3 2 1]);
isequal(allCombinationsMat, allPerms)
ans = logical
1
  댓글 수: 2
mohamed Faraj
mohamed Faraj 2019년 8월 14일
Thank you Adam. The vectors are generated by the code itself. I saved these vectors which I got from matlab in a matrix or a cell aray with a name, e.g., x{1}=1:3, x{2}=b = 11:13, x{3}=-4:1,x{4}=9.
Adam Danz
Adam Danz 2019년 8월 14일
Sounds good. So your variable "x" is my variable "allVecs". Did you have any trouble implementing the rest of the solution?

댓글을 달려면 로그인하십시오.


Bruno Luong
Bruno Luong 2019년 8월 13일
편집: Bruno Luong 2019년 8월 13일
a=[1 2 3], b=[4 5 6 7], c=[8 9 10 11 12]
C = {a,b,c}; % put you vectors here
n = length(C);
[C{:}] = ndgrid(C{:});
C = reshape(cat(n+1,C{:}),[],n)
  댓글 수: 2
Mohamad Javadzadeh
Mohamad Javadzadeh 2021년 6월 18일
Hi
Tnx for your great anwser
could we limit sum of rows?
Bruno Luong
Bruno Luong 2022년 3월 16일
편집: Bruno Luong 2024년 3월 25일 14:02
"could we limit sum of rows?"
Simply post filter what you want to keep (such as limit of sum) afterward.

댓글을 달려면 로그인하십시오.


Chris
Chris 2019년 8월 14일
I use allcomb from the Exchange - works great. Works with chars too. It uses ndgrid under the hood and is probably mostly a packaged up version of the code other have shown here.

카테고리

Help CenterFile Exchange에서 Loops and Conditional Statements에 대해 자세히 알아보기

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by