如何使用矢量化代码在 MATLAB 中从两个向量生成所有对?

发布于 2024-12-04 17:22:53 字数 539 浏览 1 评论 0原文

现在我不止一次需要在 MATLAB 中生成所有可能的两个向量对,我使用 for 循环来执行此操作,这会占用相当多的代码行,即

vec1 = 1:4;
vec2 = 1:3;
i = 0;
pairs = zeros([4*3 2]);
for val1 = vec1
    for val2 = vec2
         i = i + 1;
         pairs(i,1) = val1;
         pairs(i,2) = val2;
    end
end

生成...

1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
4 1 
4 2
4 3

必须有一种更好的方法来执行此操作,这比 MATLAB 更有效'式?

nb nchoosek 不执行我需要的反转对(即 2 1 以及 1 2),我不能只是反转并附加 nchoosek 输出,因为对称对将被包含两次。

More than once now I have needed to generate all possible pairs of two vectors in MATLAB which I do with for loops which take up a fair few lines of code i.e.

vec1 = 1:4;
vec2 = 1:3;
i = 0;
pairs = zeros([4*3 2]);
for val1 = vec1
    for val2 = vec2
         i = i + 1;
         pairs(i,1) = val1;
         pairs(i,2) = val2;
    end
end

Generates ...

1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
4 1 
4 2
4 3

There must be a better way to do this which is more MATLAB'esque?

n.b. nchoosek does not do the reversed pairs which is what I need (i.e. 2 1 as well as 1 2), I can't just reverse and append the nchoosek output because the symmetric pairs will be included twice.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

层林尽染 2024-12-11 17:22:53

尝试

[p,q] = meshgrid(vec1, vec2);
pairs = [p(:) q(:)];

查看 MESHGRID 文档。虽然这并不完全是该函数的用途,但如果你仔细看看它,你会发现你所要求的正是它的作用。

Try

[p,q] = meshgrid(vec1, vec2);
pairs = [p(:) q(:)];

See the MESHGRID documentation. Although this is not exactly what that function is for, but if you squint at it funny, what you are asking for is exactly what it does.

时光礼记 2024-12-11 17:22:53

您可以使用

a = 1:4;
b = 1:3;
result = combvec(a,b);
result = result'

You may use

a = 1:4;
b = 1:3;
result = combvec(a,b);
result = result'
海的爱人是光 2024-12-11 17:22:53

您可以通过使用 repmat 复制矩阵,然后使用 reshape 将结果转换为列向量来实现。

a = 1:4;
b = 1:3;
c = reshape( repmat(a, numel(b), 1), numel(a) * numel(b), 1 );
d = repmat(b(:), length(a), 1);
e = [c d]

e =

     1     1
     1     2
     1     3
     2     1
     2     2
     2     3
     3     1
     3     2
     3     3
     4     1
     4     2
     4     3

当然,您可以删除上面示例中的所有中间变量。

You could do it by replicating the matrices using repmat and then turning the result into a column vector using reshape.

a = 1:4;
b = 1:3;
c = reshape( repmat(a, numel(b), 1), numel(a) * numel(b), 1 );
d = repmat(b(:), length(a), 1);
e = [c d]

e =

     1     1
     1     2
     1     3
     2     1
     2     2
     2     3
     3     1
     3     2
     3     3
     4     1
     4     2
     4     3

Of course, you can get rid of all the intermediate variables from the example above.

独孤求败 2024-12-11 17:22:53

另一种收集解决方案:

[idx2, idx1] = find(true(numel(vec2),numel(vec1)));
pairs = [reshape(vec1(idx1), [], 1), reshape(vec2(idx2), [], 1)];

Another solution for collection:

[idx2, idx1] = find(true(numel(vec2),numel(vec1)));
pairs = [reshape(vec1(idx1), [], 1), reshape(vec2(idx2), [], 1)];
迷荒 2024-12-11 17:22:53

您正在寻找的是 笛卡尔积

cartprod 是实现它的函数。您可以在线性代数包中找到它,因此您需要执行以下操作:

   >> pkg install -forge linear-algebra
   >> pkg load linear-algebra 
   >> sortrows(cartprod(1:4,1:3))                                            
    ans =                                                                                           
       1   1                                                                  
       1   2                                                                  
       1   3                                                                  
       2   1                                                                  
       2   2                                                                  
       2   3                                                                  
       3   1                                                                  
       3   2                                                                  
       3   3                                                                  
       4   1                                                                  
       4   2                                                                  
       4   3    

What you are looking for is the cartesian product

cartprod is the function that implements it. You can find it in the linear-algebra package so you would need to do:

   >> pkg install -forge linear-algebra
   >> pkg load linear-algebra 
   >> sortrows(cartprod(1:4,1:3))                                            
    ans =                                                                                           
       1   1                                                                  
       1   2                                                                  
       1   3                                                                  
       2   1                                                                  
       2   2                                                                  
       2   3                                                                  
       3   1                                                                  
       3   2                                                                  
       3   3                                                                  
       4   1                                                                  
       4   2                                                                  
       4   3    
关于从前 2024-12-11 17:22:53

您可以使用普通的旧矩阵运算,例如在

x = [3,2,1];
y = [11,22,33,44,55];
v = [(ones(length(y),1) * x)(:), (ones(length(x), 1) * y)'(:)]

编辑:中,这是Octave语法,MATLAB将如下所示:

x = [3,2,1];
y = [11,22,33,44,55];
A = ones(length(y),1) * x;
B = (ones(length(x), 1) * y)';
v = [A(:) B(:)]

在这两种情况下,结果将是

v =
 3    11
 3    22
 3    33
 3    44
 3    55
 2    11
 2    22
 2    33
 2    44
 2    55
 1    11
 1    22
 1    33
 1    44
 1    55

You can use plain old matrix operations, e.g. in

x = [3,2,1];
y = [11,22,33,44,55];
v = [(ones(length(y),1) * x)(:), (ones(length(x), 1) * y)'(:)]

Edit: this is Octave syntax, MATLAB will look like this:

x = [3,2,1];
y = [11,22,33,44,55];
A = ones(length(y),1) * x;
B = (ones(length(x), 1) * y)';
v = [A(:) B(:)]

in both cases, result will be

v =
 3    11
 3    22
 3    33
 3    44
 3    55
 2    11
 2    22
 2    33
 2    44
 2    55
 1    11
 1    22
 1    33
 1    44
 1    55
孤芳又自赏 2024-12-11 17:22:53

从 MATLAB R2023a 开始,您可以使用组合函数来执行此操作。详细信息请参见 https://blogs.mathworks.com/matlab/2023/04/04/the-new-combinations-function-in-matlab-for-cartesian-products-and-parameter-sweeps/

> A = [1,2,3];B=[4,5];
>> C = combinations(A,B)
C =
6×2 table
A    B
_    _
1    4
1    5
2    4
2    5
3    4
3    5

结果是一个表。当所有数据类型兼容时(就像这里的情况),你可以得到这样的矩阵

>> C.Variables
ans =
1     4
1     5
2     4
2     5
3     4
3     5

As of MATLAB R2023a, you can use the combinations function to do this. Details at https://blogs.mathworks.com/matlab/2023/04/04/the-new-combinations-function-in-matlab-for-cartesian-products-and-parameter-sweeps/

> A = [1,2,3];B=[4,5];
>> C = combinations(A,B)
C =
6×2 table
A    B
_    _
1    4
1    5
2    4
2    5
3    4
3    5

The result is a table. When all data types are compatible (as is the case here) you can get the matrix like this

>> C.Variables
ans =
1     4
1     5
2     4
2     5
3     4
3     5
森林迷了鹿 2024-12-11 17:22:53

这里有一种更类似于 MATLAB 的方法来查找组合。这个也可以很容易地扩展到超过 2 个向量(以及非数字组合):

v1 =   1:  1:  3;
v2 =  11: 11: 44;
v3 = 111:111:555;

dimensions = cellfun(@numel, {v1,v2,v3});

[i1,i2,i3] = ind2sub(dimensions, 1:prod(dimensions));

combinations = [v1(i1); v2(i2); v3(i3)]'

Here a more MATLAB'esque way to find the combinations. This one can also be easily extended to more then 2 vectors (and also non-numerical combinations):

v1 =   1:  1:  3;
v2 =  11: 11: 44;
v3 = 111:111:555;

dimensions = cellfun(@numel, {v1,v2,v3});

[i1,i2,i3] = ind2sub(dimensions, 1:prod(dimensions));

combinations = [v1(i1); v2(i2); v3(i3)]'
桃酥萝莉 2024-12-11 17:22:53

从版本 R2015a 开始,您可以使用 repelem 来执行此操作repmat

>> vec1 = 1:4;
>> vec2 = 1:3;
>> pairs = [repelem(vec1(:), numel(vec2)) ...
            repmat(vec2(:), numel(vec1), 1)]

pairs =

     1     1
     1     2
     1     3
     2     1
     2     2
     2     3
     3     1
     3     2
     3     3
     4     1
     4     2
     4     3

这种类型的解决方案避免了某些其他解决方案(例如基于 meshgrid),这可能会导致较大向量的内存问题。

Starting from version R2015a, you can do this using repelem and repmat:

>> vec1 = 1:4;
>> vec2 = 1:3;
>> pairs = [repelem(vec1(:), numel(vec2)) ...
            repmat(vec2(:), numel(vec1), 1)]

pairs =

     1     1
     1     2
     1     3
     2     1
     2     2
     2     3
     3     1
     3     2
     3     3
     4     1
     4     2
     4     3

This type of solution avoids the additional intermediate variables required by some of the other solutions (such as those based on meshgrid) which could lead to memory issues for larger vectors.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文