角落案例,意外和不寻常的MATLAB

Mik*_*ail 28 matlab

多年来,在阅读其他代码时,我遇到并收集了一些MATLAB语法的例子,这些例子起初可能不常见且违反直觉.请随时评论或补充此列表.我用r2006a验证了它.


MATLAB 总是将函数的第一个输出参数(如果它至少有一个)返回到其调用者工作空间,如果调用函数而不返回参数,myFunc1(); myFunc2();则调用者工作空间仍然会包含第一个输出myFunc2();为"不可见" ans变量.如果它ans是一个参考对象,它可以发挥重要作用- 它将保持活力.


set([], 'Background:Color','red')
Run Code Online (Sandbox Code Playgroud)

MATLAB有时很宽容.在这种情况下,将属性设置为对象数组也可以使用无意义属性,至少在数组为空时.这种阵列通常来自harray = findobj(0,'Tag','NotExistingTag')


myArray([1,round(end/2)])
Run Code Online (Sandbox Code Playgroud)

end关键字的使用可能看起来不干净,但有时非常方便而不是使用length(myArray).


any([]) ~= all([])
Run Code Online (Sandbox Code Playgroud)

惊人地any([])返回falseall([])返回true.我一直认为那all更强大any.

编辑:

不为空的参数all()返回true给值的子集为其中any()返回true(例如真值表).这意味着any() false暗示all() false.MATLAB以[]参数的形式违反了这个简单的规则.

洛伦还在博客上写了这篇文章.


Select(Range(ExcelComObj))
Run Code Online (Sandbox Code Playgroud)

程序样式COM对象方法调度.不要奇怪exist('Select')回报为零!


[myString, myCell]
Run Code Online (Sandbox Code Playgroud)

在这种情况下,MATLAB将字符串变量隐式转换myString为单元格类型{myString}.如果我不希望它这样做,它也可以工作.


[double(1.8), uint8(123)] => 2 123
Run Code Online (Sandbox Code Playgroud)

另一个演员的例子 每个人都可能期望uint8值得投入,double但Mathworks有另一种观点.没有警告,这种行为非常危险.


a = 5;
b = a();
Run Code Online (Sandbox Code Playgroud)

它看起来很傻但你可以用圆括号调用变量.实际上它是有道理的,因为这样你就可以执行一个给定句柄的函数.


语法Foo(:)不仅适用于数据,还适用于调用Bar.Foo(:)的函数,在这种情况下,函数输入参数作为char 冒号 传递':'.

例如,让我们在MATLAB命令窗口中Bar.Foo = @(x) disp(x) 调用Bar.Foo(:)print char ':'.

这个奇怪的功能适用于所有MATLAB 7版本,没有任何警告.


a = {'aa', 'bb'
'cc', 'dd'};
Run Code Online (Sandbox Code Playgroud)

令人惊讶的是,这段代码既不返回矢量也不会产生错误但只使用代码布局来定义矩阵.这可能是远古时代的遗物.

编辑:非常方便的功能,请参阅gnovice的评论.


set(hobj, {'BackgroundColor','ForegroundColor'},{'red','blue'})
Run Code Online (Sandbox Code Playgroud)

此代码执行您可能期望它执行的操作.该函数set接受一个结构,因为它的第二个参数是一个已知的事实并且有意义,而这个sintax只是一个cell2struct消失.


首先,等价规则有时会出乎意料.例如,'A'==65返回true(尽管对于C-experts来说这是不言而喻的).类似地isequal([],{}),按预期返回falseisequal([],'')返回true.

字符串数字等价意味着所有字符串函数也可用于数值数组,例如,查找大数组中子数组的索引:

ind = strfind( [1 2 3 4 1 2 3 4 1 2 3 4 ], [2 3] )
Run Code Online (Sandbox Code Playgroud)

MATLAB函数isnumeric()返回false布尔值.这感觉只是......假:-)


关于哪些进一步的意外/不寻常的MATLAB功能你知道吗?

Jon*_*nas 12

图像坐标与绘图坐标用于每次都得到我.

%# create an image with one white pixel
img = zeros(100);
img(25,65) = 1;

%# show the image
figure
imshow(img);

%# now circle the pixel. To be sure of the coordinate, let's run find
[x,y] = find(img);
hold on
%# plot a red circle...
plot(x,y,'or')
%# ... and it's not in the right place

%# plot a green circle with x,y switched, and it works
plot(y,x,'og')
Run Code Online (Sandbox Code Playgroud)

编辑1

数组尺寸

变量至少有两个维度.标量是大小[1,1],向量是大小[1,n][n,1].因此,ndims对于它们中的任何一个返回2(实际上,ndims([])也是2,因为size([])[0,0]).这使得测试输入的维数变得有点麻烦.要检查1D阵列,必须使用isvector0D阵列isscalar.

编辑2

数组赋值

通常,Matlab对阵列分配很严格.例如

m = magic(3);
m(1:2,1:3) = zeros(3,2);
Run Code Online (Sandbox Code Playgroud)

抛出一个

??? Subscripted assignment dimension mismatch.
Run Code Online (Sandbox Code Playgroud)

但是,这些工作:

m(1:2,1:2) = 1; %# scalar to vector
m(2,:) = ones(3,1); %# vector n-by-1 to vector 1-by-n (for newer Matlab versions)
m(:) = 1:9; %# vector to 'linearized array'
Run Code Online (Sandbox Code Playgroud)

编辑3

使用错误大小的数组进行逻辑索引祝你好运!

逻辑索引似乎会调用find,因为您的逻辑数组不需要与索引相同数量的元素!

>> m = magic(4); %# a 4-by-4 array
>> id = logical([1 1 0 1 0])
id =
     1     1     0     1     0
>> m(id,:)  %# id has five elements, m only four rows
ans =
    16     2     3    13
     5    11    10     8
     4    14    15     1
%# this wouldn't work if the last element of id was 1, btw

>> id = logical([1 1 0])
id =
     1     1     0
>> m(id,:) %# id has three elements, m has four rows
ans =
    16     2     3    13
     5    11    10     8
Run Code Online (Sandbox Code Playgroud)


gno*_*ice 8

我不会列出奇怪的MATLAB语法示例,而是会解决我认为有意义或预期/记录/期望行为的问题中的一些示例.

  • ANYALL如何处理空参数:

    结果是any([])有道理的:输入向量中没有非零元素(因为它是空的),所以它返回false.

    all([])通过考虑如何实现自己的此函数版本,可以更好地理解结果:

    function allAreTrue = my_all(inArray)
      allAreTrue = true;
      N = numel(inArray);
      index = 1;
      while allAreTrue && (index <= N)
        allAreTrue = (inArray(index) ~= 0);
        index = index + 1;
      end
    end
    
    Run Code Online (Sandbox Code Playgroud)

    此函数循环遍历元素,inArray直到遇到零为零.如果inArray为空,则永远不会输入循环并allAreTrue返回默认值.

  • 连接不像类:

    当将不同类型连接成一个数组时,MATLAB遵循预设的类优先级并相应地转换值.一般优先顺序(从最高到最低)为:char,integer(任何标志或比特数的), ,single,doublelogical.这就是为什么[double(1.8), uint8(123)]会给你一个类型的结果uint8.当组合不同于整数类型(uint8,int32等)时,最左边的矩阵元素确定结果的类型.

  • 不使用行继续运算符(...)的多行:

    构造具有多行的矩阵时,只需在输入一行后点击返回并在下一行输入下一行,而不必使用分号来定义新行或...继续行.因此,以下声明是等效的:

    a = {'aa', 'bb'
    'cc', 'dd'};
    
    a = {'aa', 'bb'; ...
    'cc', 'dd'};
    
    a = {'aa', 'bb'; 'cc', 'dd'};
    
    Run Code Online (Sandbox Code Playgroud)

    你为什么要让MATLAB表现得像这样?我注意到的一个原因是它可以很容易地将数据从例如Excel文档剪切并粘贴到MATLAB命令窗口中的变量中.请尝试以下方法:

    • 在Excel文件中选择一个区域并进行复制.
    • 键入a = [到MATLAB 没有击中回报.
    • 右键单击MATLAB命令窗口并选择"粘贴".
    • 输入];并点击返回.现在,您有一个变量a,其中包含您在Excel文件中选择的行和列中的数据,并保留数据的"形状".


Rom*_*kov 5

阵列与细胞

我们来看看一些基本语法.要创建包含元素a,b,c的数组,请编写[a b c].要编写包含数组A,B,C的单元格{A B C}.到现在为止还挺好.

访问数组元素的方法如下:arr(i).对于细胞,它是cell{i}.还好.

现在让我们尝试删除一个元素.对于数组:arr(i) = [].从上面的示例推断,您可能会尝试cell{i} = {}单元格,但这是一个语法错误.实际上,删除单元格元素的正确语法与数组使用的语法完全相同:cell(i) = [].

因此,大多数情况下使用特殊语法访问单元格,但删除项目时使用数组语法.

如果你深入挖掘,你会发现实际上一个单元格是一个数组,其中每个值都是某种类型.所以你仍然可以写cell(i),你只会得到{A}(一个单值的单元!).cell{i}A直接检索的简写.

这一切都不是很漂亮的IMO.

  • 单元格行为实际上非常一致:arr(i)返回数组的第i个元素.在数值数组的情况下,第i个元素是数字标量,在单元格数组的情况下,第i个元素是标量单元格,在结构数组的情况下,第i个元素是标量结构.花括号用于"挖掘"单元格,就像字段名用于"挖掘"结构一样.此外,与结构类似,您可以继续访问单元格内容的元素,例如cellArray {i}(1,2) (6认同)