Matlab数组的动态切片 [英] Dynamic slicing of Matlab array

查看:740
本文介绍了Matlab数组的动态切片的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个n维数组A,想要动态切片,即给定一个数组维度的列表,如[2 4]和一个值列表,如[6 8],我想要

  B = A(,,,6,...,8,...,...,,,,...)

列表长度未知。使用eval将工作,但不是一个选项。这个问题是将上一篇文章推广到多个索引和维度,而没有for-loop。

解决方案

您仍然可以使用之前的帖子我链接到(我原来标记为重复)来回答你的问题。这个原始帖子只在一个维度上切片。我原来将其标记为重复,并关闭它,因为您需要做的是在原始帖子接受的答案中替换一行代码,以实现您想要的。但是,由于这不是很明显,我决定重新开启这个问题,并回答你的问题。



参考上一篇文章,这是 Andrew Janke < a>(在链接的帖子上有接受答案的人)(非常聪明我可能会添加):

  function out = (A,ix,dim)

subses = repmat({':'},[1 ndims(A)]);
subses {dim} = ix;
out = A(subses {:});

给定矩阵 A ,索引号 ix 和您要访问的维度 dim ,上述功能将等效执行:

  out = A(:,,...,ix,...,...,... :); 
^ ^ ^ ^
dimensions - > 1 2 dim dim + 1

您可以在 dim ,并将要使用的值放入该维度。因此,您可以这样调用:

  out = slice(A,ix,dim); 

功能如何工作是 subses 生成':'字符串的单元格数组(最终将转换为:运算符),只要维数的总和 A 。接下来,您将访问 dim 的元素,这对应于您想要的维度,您将用 ix 。然后,您将展开该单元格数组,以便我们以您在上述等效语句中看到的方式访问 A


谁会以为你可以使用字符串来索引到数组!


现在,为了概括一下,你所要做的只是做一个小但非常关键的变化。 ix 现在将是一个向量的索引,而 dim 将是您要访问的维度的向量因此,它看起来像这样:

  function out = slice(A,ix,dim)

subses = repmat({':'},[1 ndims(A)]);
subses(dim)= num2cell(ix);
out = A(subses {:});

我们在这里看到的唯一区别是代码的第二行。我们必须使用 num2cell ,以便您可以将每个元素转换为单元格数组,并将其切割到此单元格数组中以将所需维度替换为运算符。请注意,我们使用()大括号和 {} 大括号。 ()大括号用于切片单元格数组,而 {} 用于访问单元格数组内容。因为我们要将多个单元格分配给子课程,需要()。然后,我们在 A 中执行切片。



因此,考虑到您的问题,并通过上述修改,您会做:

  out = slice(A,[6 8],[2 4]); 

请注意, ix dim 必须包含相同数量的元素,而必须为1D。另外, ix dim 应该是明智的输入(即不是浮点和否定)。我不会这样做错误检查,因为我假设你知道你在做什么,而且你足够聪明才能知道如何正确使用。






祝你好运!


I have an n-dimensional array A and want to slice it dynamically, i.e., given a list of array dimensions, like [2 4], and a list of values, like [6 8], I want

B = A(:,6,:,8,:,:,:,:,...)

List lengths are unknown. Using eval would work but is not an option. This question is a generalization of a previous post to multiple indices and dimensions without a for-loop.

解决方案

You can still use the previous post I linked to (which I originally flagged as a duplicate) to answer your question. This original post only slices in one dimension. I originally flagged it as a duplicate and closed it because all you need to do is replace one line of code in the original post's accepted answer to achieve what you want. However, because it isn't that obvious, I have decided to reopen the question and answer the question for you.

Referring to the previous post, this is what Andrew Janke (the person with the accepted answer on the linked post) did (very clever I might add):

function out = slice(A, ix, dim)

subses = repmat({':'}, [1 ndims(A)]);
subses{dim} = ix;
out = A(subses{:});

Given a matrix A, an index number ix and the dimension you want to access dim, the above function would equivalently perform:

        out = A(:, :, ..., ix, :, :,...:);
                ^  ^        ^  ^  
dimensions -->  1  2       dim dim+1

You would access your desired dimension in dim, and place what value you want to use to slice into that dimension. As such, you'd call it like this:

out = slice(A, ix, dim);

How the function works is that subses would generate a cell array of ':' strings (that will eventually be converted into ':' operators) that is as long as the total number of dimensions of A. Next, you would access the element at dim, which corresponds to the dimension you want and you would replace this with ix. You would then unroll this cell array so that we would access A in the manner that you see in the above equivalent statement.

Who would have thought that you can use strings to index into an array!?

Now, to generalize this, all you have to do is make one small but very crucial change. ix would now be a vector of indices, and dim would be a vector of dimensions you want to access. As such, it would look something like this:

function out = slice(A, ix, dim)

subses = repmat({':'}, [1 ndims(A)]);
subses(dim) = num2cell(ix);
out = A(subses{:});

The only difference we see here is the second line of the code. We have to use num2cell so that you can convert each element into a cell array, and we slice into this cell array to replace the : operators with your desired dimensions. Note that we are using () braces and not {} braces. () braces are used to slice through cell arrays while {} are used to access cell array contents. Because we are going to assign multiple cells to subses, () is needed. We then perform our slicing in A accordingly.

As such, given your problem and with the above modifications, you would do:

out = slice(A, [6 8], [2 4]);

Be advised that ix and dim must contain the same number of elements and they must be 1D. Also, ix and dim should be sensible inputs (i.e. not floating point and negative). I don't do this error checking because I'm assuming you know what you're doing and you're smart enough to know how to use this properly.


Good luck!

这篇关于Matlab数组的动态切片的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆