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

Arg*_*yll 5 arrays matlab

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

例如,[1:4,5:.5:7]

1, 2, 3, 4, 5, 5.5, 6, 6.5, 7
Run Code Online (Sandbox Code Playgroud)

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

Lui*_*ndo 4

这是一个解决方案

\n\n
    \n
  • 充分处理不形成范围的数字。例如,[1 3 5 9]将输出为\'[1:2:5 9]\'. 同样,[1 3 5 9 11]会给出\'[1:2:5 9 11]\'.
  • \n
  • 省略指定步骤1。例如,[9 3 4 5]将给出[9 3:5].
  • \n
  • 省略不必要的括号。例如,[8 6 4 2]会给出\'8:-2:2\',并且5会给出\'5\'
  • \n
  • 允许空输入。所以[]会给予\'[]\'
  • \n
\n\n

\n\n

x = [2 4.5 7 9.5 9 8 7 6 5 15 7.5 7 6.5 6 9 11]; % example input\nsep = \' \'; % define separator; it could also be comma\nstr = \'\'; % initiallize output\nk = 1; % first number not processed yet\nwhile k<=numel(x)\n    m = find(diff([diff(x(k:end)) inf]), 1) + 1; % may be empty\n    if m>2 % if non-empty and at least 2: range found (at least 3 numbers)\n        ini = x(k);\n        ste = x(k+1)-x(k);\n        fin = x(k+m-1);\n        if ste~=1\n            str = [str num2str(ini) \':\' num2str(ste) \':\' num2str(fin)];\n        else\n            str = [str num2str(ini) \':\' num2str(fin)];\n        end\n        k = k+m; % m numbers have been processed\n    else % no range: include just one number\n        str = [str num2str(x(k))];\n        k = k+1; % 1 number has been processed\n    end\n    str = [str sep]; % add separator\nend\nstr = strip(str,sep); % this removes trailing space/comma, if it exists. For pre-2016b, use `strtrim`\nif any(str==sep) || isempty(str)\n    str = [\'[\' str \']\']; % brackets are required\nend\n
Run Code Online (Sandbox Code Playgroud)\n\n

示例/测试:

\n\n
    \n
  • [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]\'
  • \n
  • [1.5 16 -0.5 -7 -9 -11]给出\'[1.5 16 -0.5 -7:-2:-11]\'
  • \n
  • [4 2 0 -2 5 12 19]给出\'[4:-2:-2 5:7:19]\'
  • \n
  • [-2 0 2.5 5.5]给出\'[-2 0 2.5 5.5]\'
  • \n
  • [2 3 4 10 7 8]给出\'[2:4 10 7 8]\'
  • \n
  • [6 4.5 3]给出\'6:-1.5:3\'
  • \n
  • [3 4 5 6]给出\'3:6\'
  • \n
  • 42给出\'42\'
  • \n
  • []给出\'[]\'
  • \n
\n\n

该代码由一个循环组成,该循环从当前位置开始搜索最大长度范围,然后向前移动。最棘手的部分是线条

\n\n
\n

m = find(diff([diff(x(k:end)) inf]), 1) + 1; % may be empty

\n
\n\n

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

\n\n
    \n
  • 3 个或更多数字的正确范围,后跟至少一个不在该范围内的数字。例如,如果x(k:end)is[3 5 7 15]我们有diff(x(k:end))等于[2 2 8]diff([diff(x(k:end)) inf])等于[0 6 inf]find(..., 1)给出2mis 3
  • \n
  • 3 个或更多数字的正确范围,结束数组。例如,如果x(k:end)is[3 5 7]我们有diff(x(k:end))等于[2 2]diff([diff(x(k:end)) inf])等于[0 inf]find(..., 1)给出2mis 3。这就是为什么inf需要;如果没有它,结果将为m=[],分支将错误地将其解释为“无范围” if
  • \n
  • 没有合适的范围;还剩2个以上的号码。例如,如果x(k:end)is[3 6 7]我们有diff(x(k:end))等于[3 1]diff([diff(x(k:end)) inf])等于[-2 inf]find(..., 1)给出1mis 2。这意味着存在两个数字的范围;但这不是一个合适的范围,因此if分支将忽略它,并继续执行该else部分。
  • \n
  • 没有合适的范围;只剩下2个号码了。例如,如果x(k:end)is[3 6]我们有diff(x(k:end))等于3diff([diff(x(k:end)) inf])等于[inf]find(..., 1)给出1mis 2。同样,两个数字有一个范围,但这不是一个适当的范围。请注意,如果没有包含,inf我们将m=[]代替“正确” 2,但这也可以有效触发该部分(其中未使用 的else实际值)。m
  • \n
  • 没有合适的范围;只剩下1个数字,即当前数字结束数组。例如,我们有if x(k:end)等于、等于、给出、并且是。尽管“应该”是,但对于触发该部分同样有效。3diff(x(k:end))[]diff([diff(x(k:end)) inf])[]find(..., 1)[]m[]m1[]else
  • \n
\n\n

请注意,由于输入包含整数或半整数,因此不存在浮点精度问题,因为这些数字精确表示到 \xc2\xb1 2^52

\n