【问题标题】:Access matrix with colons programmatically以编程方式访问带有冒号的矩阵
【发布时间】:2015-06-26 13:18:29
【问题描述】:

我有一个矩阵a,维数未知。

我想像a(:,:,:,:,:, ... ,:,1) 一样访问它。也就是说,只设置最后一个维度。

如何做到这一点无需进行大量数学运算并将 a 视为一维数组。我知道这个解决方案有效,但是当每个维度都有不同的大小(而且你甚至不知道维度的数量)时,它是一团糟并且很难实现

【问题讨论】:

  • 当你说“访问它”时,你是想提取数组的那一部分,比如b = a(:,:, ..., 1),还是想设置成a(:,:, ..., 1) = b,或者别的什么?跨度>
  • 阅读和设置有区别吗?在这种情况下,我希望两者都能做到。
  • 是的。基本上,要分配,您需要一个“左值”,这意味着a)您使用的任何技术都必须直接索引到原始数组(或通过重塑和重新分配进行补偿),以及b)如果您将其包装在一个函数中,则赋值必须发生在函数内部,而不是仅仅返回索引。我已经用 slice 函数的一个变体更新了我对另一个问题的回答。

标签: matlab


【解决方案1】:
% get number of dimensions of a
d = ndims(a)

% create cell array with indexes for each dimension
indexes = repmat({':'}, 1, d-1)
indexes{end+1} = 1

% access matrix
a(indexes{:})

【讨论】:

  • +1。这是一个足够常见的操作,我喜欢将它打包到 slice() 函数中。这里有一个更长的讨论,关于本质上相同的问题。 stackoverflow.com/questions/22537326/…
  • 虽然问题是一样的,但我只是认为另一个问题没有很好地表述。在发布我的问题之前我搜索了半小时,但找不到您发布的此链接。
  • 好点;如果您还不知道那个特定的、非显而易见的术语,就很难找到它。值得拥有实时和可搜索的。我正在从这个问题中删除我的“重复”投票。
【解决方案2】:

我和你的看法不同。你说:

我知道这个(考虑为一维数组)解决方案有效,但是当每个维度都有不同的大小时(而且你甚至不知道维度的数量),它是一团糟并且很难实现

我不这么认为。让我给你看看。

MATLAB 是列优先的,即如果您告诉 MATLAB 将一个 n-D 矩阵折叠成一维向量,它会执行以下步骤:

  1. 取第一个维度。
  2. 获取第一列,将第二列附加到它,然后是第三列,依此类推。这样,它会折叠第一个维度。
  3. 然后取下一个维度,重复第二步,将得到的向量追加到当前向量上。 (直到你完成所有维度)。

以此为例:

a=randi(12,2,2,2,2)

a(:,:,1,1) =

 7     8
10     5


a(:,:,2,1) =

 4     6
 6     5


a(:,:,1,2) =

 7     6
 9     6


a(:,:,2,2) =

 2     4
 1     4

折叠矩阵a

b=a(:)

b =

 7
10
 8
 5
 4
 6
 6
 5
 7
 9
 6
 6
 2
 1
 4
 4

现在,一旦您了解了折叠过程,就可以直接构建一个通用公式。假设您要访问最外层维度1(与问题中的完全相同)。

dimToAccess=1;
sz=size(a);
c=b(prod(sz(1:end-1))*(dimToAccess-1)+1:prod(sz(1:end-1))*(dimToAccess));

让我们测试一下。

a=randi(12,2,2,2,2)

a(:,:,1,1) =

 7     8
10     5


a(:,:,2,1) =

 4     6
 6     5


a(:,:,1,2) =

 7     6
 9     6


a(:,:,2,2) =

 2     4
 1     4

b=a(:);
dimToAccess=1;
sz=size(a);
c=b(prod(sz(1:end-1))*(dimToAccess-1)+1:prod(sz(1:end-1))*(dimToAccess));

%Test - It should produce 1 as output.
isequal(reshape(c,[size(a,1) size(a,2) size(a,3)]),a(:,:,:,dimToAccess))

答案似乎很长,但实际上只有 4 行。

【讨论】:

  • 很高兴知道这些索引转换,但 OP 使用 {':'} 的解决方案在实践中可能会更好。它很容易推广到其他维度和形式的索引,并且可能更具可读性。我发现这有点令人困惑,因为dimToAccess 不是您正在处理的维度的访问权限(始终是ndims(a));它是沿该维度的索引。
  • 另外,b=a(:) 步骤是不必要的。您可以使用单个“线性”索引直接索引到 a,并获得相同的结果。
  • @AndrewJanke 是的。甚至我更喜欢 hsgubert 的解决方案(您在之前的帖子中建议过)。我只是想告诉 OP,矩阵索引并没有那么混乱和混乱。
  • 您的代码有效,但它假定矩阵具有一定数量的维度。也许如果代码被很好地封装在一个函数中,它可能是可用的。
【解决方案3】:

只需将尺寸从最后一个移到第一个即可。

x = shiftdim(x,ndims(x)-1)

然后您可以只处理第一个元素。由于 Matlab 组织数据列专业,您无需担心所有尾随 :。只需通过索引第一个元素来索引第一列。

x(1:size(x,1)) = whatever

如果你喜欢shiftdim,可以在最后移回。

【讨论】:

  • 如果最后一个维度的索引值不是1,例如3[2 4 6],你会如何推广这个公式?
猜你喜欢
  • 2018-04-18
  • 2011-07-24
  • 2013-08-23
  • 1970-01-01
  • 2020-07-09
  • 2010-09-05
  • 1970-01-01
  • 1970-01-01
  • 2015-02-15
相关资源
最近更新 更多