【问题标题】:Removing all zero-values except for those flanking non-zero values删除除侧翼非零值之外的所有零值
【发布时间】:2016-08-03 09:05:50
【问题描述】:

给定一个向量:

a = [0;0;2;3;0;2;10;11;0;0;0;4;5;8;0;0;0]

任何人都可以展示或建议一种方法来删除所有零值,除了那些侧面非零值的值吗?

上述的期望结果是:

b = [0;2;3;0;2;10;11;0;0;4;5;8;0]

这些值已被删除:

[0;0;2;3;0;2;10;11;0;0;0;4;5;8;0;0;0]

我不知道从哪里开始解决这个问题,而不必求助于使用一组 IF 语句,例如:

for k=1:length(a)
    if a(k) == 0 && a(k+1) == 0
        *delete value*
    end
    if a(k) == 0 && a(k+1) >0
        *keep/store value*
    end
    if a(k) > 0
        *keep/store value*
    end
    if a(k) == 0 && a(k-1) >0
        *keep/store value*
    end
end

等等。

【问题讨论】:

  • 如果您的非零数字都不是成对出现,您可以使用diff - 否则您仍然可以使用diff(更智能)。我刚刚意识到,如果有连续的零你只想删除 1?
  • 任何在其左侧或右侧具有非零值的零值都将被保留 - 其余的将被删除。如果有 3 个或更多连续的零,则将删除至少 1 个,例如 [4, 8, 0, 0, 0, 0, 10] - 输出将简单地为: [4, 8, 0, 0, 10 ] - 保留符合上述条件的两个零。
  • @AnnaSchumann 如果您对解决问题的高尔夫解决方案感兴趣,see here

标签: arrays matlab vector


【解决方案1】:

我有另一个想法(当然,与其他两个没有太大区别),使用逻辑索引:

a(~(~a & ~[diff(a);0] & ~[0;diff(a)] ));

解释:

  • ~ - 布尔值not,返回一个布尔值,表示输入的“相反”。
  • ~a - 返回 a 的零元素(在您给出的示例中不是必需的,但如果您想要保留重复的非零值,这很重要)。
  • ~[diff(a);0] & ~[0;diff(a)] - 返回任一大小的导数为零的值。
  • a(~(...)) - 返回a 的值,这些值不是“两边具有相同值的零”,即b

编写相同内容的另一种方式(使用De Morgan's laws 并利用非零值的“真实性”):

a( a | [diff(a);0] | [0;diff(a)] );

您可以将其视为查找“哪些值要保留”而不是“哪些值要删除”,我能想到的定义要保留哪些值的最简单方法是“所有非零元素两边都有非零的零元素”。

【讨论】:

    【解决方案2】:

    你可以使用convolution:

    b = a(conv(abs(sign(a)), ones(3,1), 'same')>0);
    

    它的工作原理如下:

    1. a 转换为0 或1 的向量(abs(sign(a))),如果a 的条目为零,则为0,否则为1。
    2. 使用三个掩码 (conv(..., ones(3,1), 'same')) 进行卷积。因此,a 中的非零值会在其位置及其相邻位置产生非零结果。
    3. 将其与零进行比较,以创建一个逻辑向量,a 将用于索引 (a(...>0))。

    这可以很容易地概括以保持更远的邻居。具体来说,使用掩码 ones(2*N+1,1) 将直到 N 条目的零值与非零值保持距离。

    【讨论】:

      【解决方案3】:

      如果您创建两个额外的向量,一个向左移动,一个从向量a 向右移动(编辑:使用circshift,如下面的 cmets 建议):

      a       = [0;0;2;3;0;2;10;11;0;0;0;4;5;8;0;0;0];
      a_right = circshift(a,-1);
      a_left  = circshift(a,1);
      

      创建一个矩阵 M :

      M = [a,a_right,a_left];
      

      并对每一行求和:

      s = sum(M,2);
      

      然后找到不同于0的组件:

      i = find(s~=0);
      

      这将为您提供从初始向量中选择的正确索引:

      b=a(i)
      

      我明白了:

      b=[0;2;3;0;2;10;11;0;0;4;5;8;0]
      

      【讨论】:

      • 您可能希望将a_right 替换为circshift(a,-1) 并将a_left 替换为circshift(a,1)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-17
      • 1970-01-01
      • 2018-01-05
      • 2015-04-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多