Arrays 如何使用冒号运算符将半整数序列压缩为字符串表达式?(如何将列表转换为字符串)

Arrays 如何使用冒号运算符将半整数序列压缩为字符串表达式?(如何将列表转换为字符串),arrays,matlab,Arrays,Matlab,Matlab中是否有内置函数,可将半整数序列压缩为带有冒号运算符的表达式 例如,[1:4,5:5:7]给出 1, 2, 3, 4, 5, 5.5, 6, 6.5, 7 给定一个双数组,如[1,2,3,4,5,5.5,6,6.5,7],是否有一种方便的方法将其转换回[1:4,5:5:7]-或同样有效的[1:5,5.5:.5:7]-作为字符串?这里有一个简单的循环答案,假设x是你的向量,我选择1e-10作为浮点精度的差异阈值 x=[1, 2, 3, 4, 5, 5.5, 6, 6.5, 7]; d

Matlab中是否有内置函数,可将半整数序列压缩为带有冒号运算符的表达式

例如,
[1:4,5:5:7]
给出

1, 2, 3, 4, 5, 5.5, 6, 6.5, 7

给定一个双数组,如
[1,2,3,4,5,5.5,6,6.5,7]
,是否有一种方便的方法将其转换回
[1:4,5:5:7]
-或同样有效的
[1:5,5.5:.5:7]
-作为字符串?

这里有一个简单的循环答案,假设
x
是你的向量,我选择
1e-10
作为浮点精度的差异阈值

x=[1, 2, 3, 4, 5, 5.5, 6, 6.5, 7];
dx=diff(x);
a=num2str(x(1)); % first step, start the range
for n=2:numel(dx)
    if abs(dx(n)-dx(n-1))>1e-10
        if dx(n-1)~=1
        a=[a ':' num2str(dx(n-1)) ':' num2str(x(n)), ' ', num2str(x(n+1)) ];
        else
       a=[a ':' num2str(x(n)), ' ', num2str(x(n+1)) ];
        end     
    end
end
a=[a ':' num2str(dx(end)) ':' num2str(x(end))]; % last step, close the range


> a =

    '1:5 5.5:0.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];%示例输入
九月=“”;%定义分隔符;也可以是逗号
str='';%初始化输出
k=1;%第一个数字尚未处理
如果不为空且至少找到2个:范围(至少3个数字),则为k2%
ini=x(k);
ste=x(k+1)-x(k);
鳍=x(k+m-1);
如果ste~=1
str=[str num2str(ini)''num2str(ste)''num2str(fin)];
其他的
str=[str num2str(ini)''num2str(fin)];
结束
k=k+m;%m个数字已经处理
else%无范围:仅包括一个数字
str=[str num2str(x(k))];
k=k+1;%1号已处理
结束
str=[str sep];%添加分隔符
结束
str=条带(str,sep);%这将删除尾随空格/逗号(如果存在)。对于2016b之前的版本,请使用'strtrim'`
如果有(str==sep)| | isempty(str)
str=['['str']'];%括号是必需的
结束
示例/测试:

  • [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.516-0.5-7-9-11]
    给出了
    '[1.516-0.5-7:-2-11]
  • [4 2 0-2 5 12 19]
    给出了
    '[4:-2:-2 5:7:19]'
  • [-20 2.5 5.5]
    给出了
    '[-20 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;%可能为空

这将尝试从当前位置
k
开始查找构成范围的数字的最大长度
m
diff(x(k:end))
计算连续的差异,外部的
diff
检测这些差异的变化。使用
find(…,1)
计算的第一个此类更改指示不属于该范围的第一个数字。共有五种情况,第二种情况解释了为什么需要
inf

  • 3个或更多数字的正确范围,后跟至少一个不在该范围内的数字。例如,如果
    x(k:end)
    [3 5 7 15]
    我们有
    diff(x(k:end))
    等于
    [2 2 8]
    diff([diff(x(k:end))inf])
    等于
    [0 6 inf]
    查找(…,1)
    给出
    2
    ,而
    m
    3
  • 3个或更多数字的适当范围,以结束数组。例如,如果
    x(k:end)
    [3 5 7]
    我们有
    diff(x(k:end))
    等于
    [2]
    diff([diff(x(k:end))inf])
    等于
    [0 inf]
    查找(…,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]
    查找(…,1)
    给出
    1
    ,而
    m
    2
    。这意味着有两个数字的范围;但是它不是一个合适的范围,因此
    if
    分支将忽略它,执行将继续执行
    else
    部分
  • 没有合适的范围;只剩下两个号码了。例如,如果
    x(k:end)
    [36]
    我们有
    diff(x(k:end))
    等于
    3
    diff([diff(x(k:end))inf])
    等于
    [inf]
    查找(…,1)
    给出
    1
    ,而
    m
    2
    。同样,有两个数字的范围,但这不是一个合适的范围。请注意,如果没有包含的
    inf
    ,我们将使用
    m=[]
    而不是“正确的”
    2
    ,但这也将有效地触发
    else
    部分(其中未使用
    m
    的实际值)
  • 没有合适的范围;只剩下1个数字,即当前数字结束数组。例如,如果x(k:end)只是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