Matlab 中是否有内置函数将半整数序列压缩为带有冒号运算符的表达式?
例如,[1:4,5:.5:7]
给
1, 2, 3, 4, 5, 5.5, 6, 6.5, 7
给定一个 double 数组,例如
[1, 2, 3, 4, 5, 5.5, 6, 6.5, 7]
,是否有一种方便的方法将其转换回 [1:4,5:.5:7]
— 或同样有效,[1:5,5.5:.5:7]
——作为字符串?
最佳答案
这是一个解决方案
[1 3 5 9]
将输出为 '[1:2:5 9]'
.同样,[1 3 5 9 11]
会给 '[1:2:5 9 11]'
. 1
.例如,[9 3 4 5]
会给 [9 3:5]
. [8 6 4 2]
会给 '8:-2:2'
, 和 5
会给 '5'
. []
会给 '[]'
. x = [2 4.5 7 9.5 9 8 7 6 5 15 7.5 7 6.5 6 9 11]; % example input
sep = ' '; % define separator; it could also be comma
str = ''; % initiallize output
k = 1; % first number not processed yet
while k<=numel(x)
m = find(diff([diff(x(k:end)) inf]), 1) + 1; % may be empty
if m>2 % if non-empty and at least 2: range found (at least 3 numbers)
ini = x(k);
ste = x(k+1)-x(k);
fin = x(k+m-1);
if ste~=1
str = [str num2str(ini) ':' num2str(ste) ':' num2str(fin)];
else
str = [str num2str(ini) ':' num2str(fin)];
end
k = k+m; % m numbers have been processed
else % no range: include just one number
str = [str num2str(x(k))];
k = k+1; % 1 number has been processed
end
str = [str sep]; % add separator
end
str = strip(str,sep); % this removes trailing space/comma, if it exists. For pre-2016b, use `strtrim`
if any(str==sep) || isempty(str)
str = ['[' str ']']; % brackets are required
end
示例/测试:
[2 4.5 7 9.5 9 8 7 6 5 15 7.5 7 6.5 6 9 11]
给 '[2:2.5:9.5 9:-1:5 15 7.5:-0.5:6 9 11]'
[1.5 16 -0.5 -7 -9 -11]
给 '[1.5 16 -0.5 -7:-2:-11]'
[4 2 0 -2 5 12 19]
给 '[4:-2:-2 5:7:19]'
[-2 0 2.5 5.5]
给 '[-2 0 2.5 5.5]'
[2 3 4 10 7 8]
给 '[2:4 10 7 8]'
[6 4.5 3]
给 '6:-1.5:3'
[3 4 5 6]
给 '3:6'
42
给 '42'
[]
给 '[]'
该代码由一个循环组成,该循环从当前位置开始搜索最大长度范围,然后向前移动。 最棘手的部分 是线
m = find(diff([diff(x(k:end)) inf]), 1) + 1; % may be empty
这试图找到最大长度
m
形成一个范围的数字,从当前位置开始 k
. diff(x(k:end))
计算连续差异,外层 diff
检测这些差异的变化。第一个这样的变化,用 find(..., 1)
计算, 表示不属于该范围的第一个数字。有五种情况,其中第二种解释了为什么inf
需要:x(k:end)
是 [3 5 7 15]
我们有 diff(x(k:end))
等于 [2 2 8]
, diff([diff(x(k:end)) inf])
等于 [0 6 inf]
, find(..., 1)
给 2
, 和 m
是 3
. x(k:end)
是 [3 5 7]
我们有 diff(x(k:end))
等于 [2 2]
, diff([diff(x(k:end)) inf])
等于 [0 inf]
, find(..., 1)
给 2
, 和 m
是 3
.这就是为什么inf
需要;没有它,结果将是 m=[]
,这会被 if
错误地解释为“无范围”分支。 x(k:end)
是 [3 6 7]
我们有 diff(x(k:end))
等于 [3 1]
, diff([diff(x(k:end)) inf])
等于 [-2 inf]
, find(..., 1)
给 1
, 和 m
是 2
.这意味着有两个数字的范围;但它不是一个合适的范围,所以 if
分支将忽略它,并继续执行 else
部分。 x(k:end)
是 [3 6]
我们有 diff(x(k:end))
等于 3
, diff([diff(x(k:end)) inf])
等于 [inf]
, find(..., 1)
给 1
, 和 m
是 2
.同样,有两个数字的范围,但它不是一个合适的范围。请注意,没有包含 inf
我们会有 m=[]
而不是“正确的”2
,但这也可以触发 else
部分(其中不使用 m
的实际值)。 if x(k:end)
只是 3
我们有 diff(x(k:end))
等于 []
, diff([diff(x(k:end)) inf])
等于 []
, find(..., 1)
给 []
, 和 m
是 []
.虽然 m
“应该”是1
, []
与触发 else
一样有效部分。 注意,由于输入包含整数或半整数,所以有没有浮点精度问题 ,因为这些数字精确地表示为 ±
2^52
.
关于arrays - 如何使用冒号运算符将半整数序列压缩为字符串表达式? (如何将列表转换为字符串),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58226737/