Matlab中的字符串与元胞数组
1. 字符串
1.1 为什么
这两个东西拉在一起讲,是因为在2016a之前的Matlab中,要表示一个字符串的数组,只能用元胞数组。
最初的字符串在Matlab中的类型是字符,在Matlab中,一个字符就是一个长度为1的字符串,而一个字符串就是一个长度大于1的字符数组。这就造成,要表示一个字符串数组,就只能用元胞数组。因为Matrix只能是方阵……
所以当时我们要在一个图上画几条线,每条线的名字是一个字符串,就只能用元胞数组。
x = 1:10;
y = [x; x.^2; x.^3];
plot(x, y);
legends = {'y = x', 'y = x * x', 'y = x * x * x'};
legend(legends);
1.2 真正的字符串类型string
2016a之后,Matlab引入了字符串类型,string
,这个类型的引入,使得我们可以直接用字符串数组来表示字符串数组了。
x = 1:10;
y = [x; x.^2; x.^3];
plot(x, y);
legends = ["y = x", "y = x * x", "y = x * x * x"];
legend(legends);
字符串类型的是""
,字符类型是''
,居然还挺有一致性的,考虑到Matlab所有变量都是默认数组。
1.3 字符(char
) vs. 字符串(string
)
所以,如果我们用class
或者whos
来查看一个字符串变量的类型,就有如下结果:
>> s1 = ['abc', 'efg']
s1 =
'abcefg'
>> class(s1)
ans =
'char'
可以看到,一行的字符数组会被自动连接在一起,因为字符数组行向量是其本质。以前的时候,我们甚至就是用这种方式来进行字符串的拼接的。
>> s1'
ans =
6×1 char 数组
'a'
'b'
'c'
'e'
'f'
'g'
而对于字符串数组,就不会这样了。
>> s2 = ["abcd", "efg"]
s2 =
1×2 string 数组
"abcd" "efg"
>> class(s2)
ans =
'string'
大部分处理字符串的函数都可以对这两个类型进行操作,例如strcat
,strfind
, strsplit
, replace
等等。这些函数总是优先返回字符数组。
1.4 格式化字符串
对于其它语言中常见的格式化字符串,Matlab中也有,sprintf
函数。
a = 1;
b = 2;
c = 3;
s = sprintf('a = %d, b = %d, c = %d', a, b, c);
disp(s);
a = 1, b = 2, c = 3
2016a之后,Matlab又增加了一个compose
函数,用来格式化字符串,这个函数对字符串和字符数组都适用,结果略有不同。可以通过帮助和文档查看具体的用法。
>> compose('%f', rand(3))
ans =
3×3 cell 数组
{'0.278276'} {'0.188147'} {'0.088258'}
{'0.303205'} {'0.201239'} {'0.414290'}
{'0.284297'} {'0.584602'} {'0.494232'}
>> compose("%f", rand(3))
ans =
3×3 string 数组
"0.074644" "0.262734" "0.416717"
"0.442903" "0.118222" "0.030380"
"0.637427" "0.372898" "0.547681"
2. 元胞数组
元胞数组,类似于别的语言中的List
,可以存放不同类型的数据,也可以存放不同大小的数据。
2.1 创建元胞数组
元胞数组的字面量,用{}
来表示。
a = {1, 2, 3};
b = {1, 2, 3; 4, 5, 6};
元胞数组同样可以是多维的。
a = cell(2, 3, 4);
2.2 访问元胞数组
元胞数组提供了两种方式来访问元胞数组中的元素,一种是()
,一种是{}
。()
返回的是一个元胞数组,{}
返回的是元胞数组中的元素。
a = {1, 2, 3};
b = a{1};
c = a(1);
disp(b);
disp(c);
1
{[1]}
前者按照系统显示数组的约定,不显示[]
,后者{}
中显示了[]
。、
最后,元胞数组的列转换与数组是一致的,
a = {1, 2, 3};
a(:)
ans =
3×1 cell 数组
{[1]}
{[2]}
{[3]}
而相应的,{:}
会带来跟在命令行一次输入所有的元素,并用逗号隔开一样的效果。
>> a{:}
ans =
1
ans =
2
ans =
3
>> 1,2,3
ans =
1
ans =
2
ans =
3
在这样的场景中可以作为右值对多个变量赋值。这与调用函数时,返回多个值的情况是一样的。
>> [x1,x2,x3] = a{:}
x1 =
1
x2 =
2
x3 =
3
2.3 元胞数组作为左值
元胞数组作为左值时,可以用{}
来赋值,也可以用()
来赋值。
a = {1, 2, 3};
a{1} = rand(4);
a(2) = {rand(4)};
>> a
a =
1×3 cell 数组
{4×4 double} {4×4 double} {[3]}
当然,跟前面的[x1,x2,x3] = a{:}
一样,也可以用{:}
来赋值。
a = {1, 2, 3};
[a{:}] = deal(rand(4));
>> a
a =
1×3 cell 数组
{4×4 double} {4×4 double} {4×4 double}
这个deal
函数,是用来将一个值赋给多个变量的,这个函数在处理多个输出参数的时候,也是很有用的。它的参数可以是一个,此时就会拷贝到所有的输出上;也可以是多个,此时就会按照顺序赋值,要求两边逗号列表的元素个数相等。
例如:
a = {1, 2, 3};
[a{:}] = deal(1, 2, 3);
>> a
a =
1×3 cell 数组
{[1]} {[2]} {[3]}
这就相当于[a{1}, a{2}, a{3}] = deal(1, 2, 3)
。
而采用()
来访问,语义上会更简单,就是元胞数组的拷贝(右边为一个元素的元胞数组)或者逐个替换(左值和右值为长度相同的元胞数组)。
3. 结论
- Matlab中的字符串类型是
string
,字符串数组的字面量是""
,字符数组的字面量是''
。 - Matlab中的元胞数组是一种特殊的数组,可以存放任意类型的数据,也可以存放不同类型的数据。
- 通过
{:}
可以得到一个逗号分开的列表。 deal
函数,可以用来将一个值赋给多个变量,也可以用来将多个值赋给多个变量。