使用嵌套for循环生成点对

时间:2014-08-13 16:06:55

标签: matlab for-loop matrix

例如,我有一个矩阵[1,2,3,4,5]'。这个矩阵包含一列和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)。我该怎么做,对数的一般公式是什么?

2 个答案:

答案 0 :(得分:3)

一种方式,虽然受限于可供选择的不同元素的数量,但是使用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

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

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

答案 1 :(得分:1)

如果您不想依赖nchoosek,我可以添加的其他建议是生成upper triangular matrix个完整的,忽略对角线,并使用{{3}生成矩阵等于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中使用find命令,以便我们能够按照您期望的正确顺序进行:

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忍者sortrows的认可,我从Jon Skeet得到了这个。

因此,你可以试试这个:

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