【问题标题】:Generate pairs of points using a nested for loop使用嵌套的 for 循环生成点对
【发布时间】:2014-10-07 02:23:55
【问题描述】:

例如,我有一个矩阵[1,2,3,4,5]'。这个矩阵包含一列和五行,我必须生成一对像(1,2),(1,3)(1,4)(1,5),(2,3)(2,4)(2,5),(3,4)(3,5)(4,5)这样的点。

我必须将这些值存储在矩阵的 2 列中。我有以下代码,但它并没有给我正确的答案。

for s = 1:5;
    for tb = (s+1):5;
    if tb>s
        in = sub2ind(size(pairpoints),(tb-1),1);
        pairpoints(in) = s;
        in = sub2ind(size(pairpoints),(tb-1),2);
        pairpoints(in) = tb;
     end
    end
end

使用此代码,我得到了(1,2),(2,3),(3,4),(4,5)。应该怎么做,对数的一般公式是什么?

【问题讨论】:

  • 我正在删除图像处理标签,因为它不相关。
  • 另外,你想要两个对的唯一组合,所以公式实际上是nchoosek(暗指@GeoffHayes)。因此,给定N 项可供选择并一次选择k 元素,您就有N! / (k!*(N-k)!) 可能的配对。在您的情况下,N = 5k = 2,因此:5! / (2!*3!) = 10

标签: matlab for-loop matrix


【解决方案1】:

如果您不想依赖 nchoosek,我可以添加的另一个建议是生成一个充满 1 的 upper triangular matrix,忽略对角线,并使用 find 生成其中矩阵等于 1。然后您可以将这两个连接成一个矩阵。通过以这种方式生成上三角矩阵,它们等于 1 的矩阵位置与您正在寻找的行和列对完全对应。因此:

%// Highest value in your data
N = 5;
[rows,cols] = find(triu(ones(N),1));
pairpoints = [rows,cols]

pairPoints = 

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

请记住,这将是未排序的(即不是按照您在问题中指定的顺序)。如果顺序对您很重要,请在 MATLAB 中使用 sortrows 命令,以便我们可以按照您期望的正确顺序进行处理:

pairPoints = sortrows(pairPoints)

pairPoints = 

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

请注意,我为triu 指定了一个附加参数,它表示您想要远离对角线的偏移量。默认偏移量为 0,其中包括提取上三角矩阵时的对角线。我将 1 指定为第二个参数,因为我想从对角线向右移动 1 个单位,所以我不想将对角线作为上三角分解的一部分。


for循环方法

如果您真的需要 for 循环方法,与您的模型一起使用,您将需要两个 for 循环,并且您需要跟踪我们所在的上一行,以便我们可以直接跳到下一列直到最后使用它。您也可以使用@GeoffHayes 方法,只使用一个for 循环来生成索引,但是当您不熟悉一种语言时,我将始终给出的一个关键建议是编写代码以提高可读性而不是提高效率。一旦你让它工作起来,如果你有一些衡量性能的方法,你就可以尝试让代码更快更高效。这种编程也得到了 StackOverflow 常驻忍者 Jon Skeet 的认可,我是从 this post here 那里得到的。

因此,你可以试试这个:

pairPoints = []; %// Initialize
N = 5; %// Highest value in your data
for row = 1 : N
    for col = row + 1 : N
        pairPoints = [pairPoints; [row col]]; %// Add row-column pair to matrix
    end
end

我们得到等效的输出:

pairPoints =

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

小警告

仅当您的数据从1 枚举到N 时,此方法才有效。


编辑 - 2014 年 8 月 20 日

您希望将此推广到任何值数组。您还想坚持使用for 循环方法。您仍然可以将原始的 for 循环代码保留在那里。您只需添加几行来索引您的新数组。因此,假设您的数据数组是:

dat = [12, 45, 56, 44, 62]; 

您将使用pairPoints 矩阵并使用每一列对数据数组进行子集化以访问您的值。此外,您需要确保您的数据是列向量,否则这将不起作用。如果我们不这样做,我们将创建一个一维数组并连接行,这显然不是我们正在寻找的。换句话说:

dat = [12, 45, 56, 44, 62];
dat = dat(:); %// Make column vector - Important! 
N = numel(dat); %// Total number of elements in your data array
pairPoints = []; %// Initialize

%// Skip if the array is empty
if (N ~= 0)
    for row = 1 : N
        for col = row + 1 : N
            pairPoints = [pairPoints; [row col]]; %// Add row-column pair to matrix
        end
    end

    vals = [dat(pairPoints(:,1)) dat(pairPoints(:,2))];
else
    vals = [];

请注意,我已经做出了规定,如果数组为空,则不必费心进行任何计算。只输出一个空矩阵。

因此我们得到:

vals =

12    45
12    56
12    44
12    62
45    56
45    44
45    62
56    44
56    62
44    62

【讨论】:

  • 啊哈使用下标! :D
  • 这些是一般值,如果我想存储一些这样的矩阵值,那么我应该怎么做,例如我必须为值 {12 , 45, 56,44, } 配对然后如何生成那种矩阵,因为上面的代码只生成从 1... 到向前的值,请指导我谢谢
  • @user3781516 这很简单。您只需再添加几行即可。我会更新我的答案。
  • 谢谢它的工作,如果我们的矩阵中的值为零,那么它会给出错误,我该怎么办
  • 显然行不通。如果没有元素,您需要一个 if 语句跳过此语句。我再编辑一次。
【解决方案2】:

一种方法是使用nchoosek,尽管取决于有多少不同的元素可供选择,但会受到限制

 pairpoints = nchoosek([1:5],2)

 pairpoints =
   1     2
   1     3
   1     4
   1     5
   2     3
   2     4
   2     5
   3     4
   3     5
   4     5

在提供的链接中查看此功能的限制。

另一种方法是迭代每个元素并将其与列表中的其余元素组合(假设所有元素都是不同的)

pairpoints = [];
data       = [1:5]';

len        = length(data);

for k=1:len
     pairpoints = [pairpoints ; [repmat(data(k),len-k,1) data(k+1:end)]];
end

此方法只是将 data 中的每个元素与列表中的其余元素连接起来以获得所需的对。

尝试以上任一方法,看看会发生什么!

【讨论】:

    猜你喜欢
    • 2020-03-02
    • 2017-10-05
    • 2021-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-15
    相关资源
    最近更新 更多