通常使用end
关键字作为在Matlab中访问或扩展数组的快捷方式,如
>> x = [1,2,3];
>> x(1:end-1)
ans =
1 2
>> x(end+1) = 4
x =
1 2 3 4
然而,我惊讶地发现以下内容也有效
>> x(1:min(5, end))
ans =
1 2 3 4
我认为end
可能是一种特殊形式,如:
,可以在索引操作中使用特殊形式,因此我创建了一个类来检测此
classdef IndexDisplayer
methods
function subsref(self, s)
disp(s);
end
end
end
您可以在以下示例
中查看:
的特殊情况
>> a = IndexDisplayer;
>> a(1:3)
type: '()'
subs: {[1 2 3]}
>> a(:)
type: '()'
subs: {':'}
然而,当我用end
索引时,我只看到
>> a(end)
type: '()'
subs: {[1]}
此处end
已替换为1
。 1
来自哪里?我的第一个猜测是,索引表达式end
中的任何x(end)
都会被调用length(x)
所取代,所以我尝试覆盖length
classdef IndexDisplayer
methods
function subsref(self, s)
disp(s);
end
function len = length(self)
len = 10;
end
end
end
然而,这给出了
>> a = IndexDisplayer;
>> length(a)
ans =
10
>> a(end)
type: '()'
subs: {[1]}
这样理论就不在窗外了。任何人都可以解释end
的语义吗?
答案 0 :(得分:17)
首先,我认为你的语法x(1:min(5, end))
是有效的,或者至少是一个意想不到的功能。当我在MathWorks时,我记得有人指出这一点,并且相当多的开发人员不得不花费一些时间来弄清楚发生了什么。我不确定他们是否真的同意这是否是一个问题。
解释end
的(预期)语义:end
实现为函数ind = end(obj, k, n)
。 k
是包含end
的表达式的索引,n
是表达式中索引的总数。
因此,例如,当您致电a(1,end,1)
时,k
为2,因为end
位于参数2中,n
为3,因为有3个参数
ind
作为可以替换表达式中的end
的索引返回。
您可以为自己的课程重载end
(与您可以重载colon
,size
,subsref
等相同的方式。
扩展你的例子:
classdef IndexDisplayer
methods
function ind = end(self,k,n)
disp(k)
disp(n)
ind = builtin('end', self, k, n);
end
end
end
>> a = IndexDisplayer;
>> a(1,end,1)
2
3
有关详细信息,请参阅here。
答案 1 :(得分:4)
我发现这也是一种好奇心。不过,我经常使用(利用?)这种行为来缩短语句。例如,在this answer中,为了获得向量的k
个元素以外的所有元素,我发现了一个干净的解决方案,
vector(setdiff(1:end,k))
此end
取代了对numel(vector)
的通话。对于标量k
,这是vector(1:end ~= k)
或vector([1:k-1 k+1:end])
的替代方案。当时看起来非常合理,虽然我提请注意这种用法的奇怪之处。这真是不好的做法吗?或许,但我已经接受了它的价值并继续前进。
我没有提供任何有关其工作原理或规则的见解,正如Sam Roberts在答案中所做的那样,但从概念上讲,我认为这是一个背景问题。也就是说,当end
发生时,我会假设它评估为具有最直接范围的数组的索引(或维度下标),查看" up"通过嵌套语句来做出决定。不确定这是否是正确的措辞,但它似乎是解释end
的操作的有用方法。
我还没有被这种解释所困扰。