代码之家  ›  专栏  ›  技术社区  ›  coorasse

用ruby删除数组中的下一个元素

  •  3
  • coorasse  · 技术社区  · 6 年前

    给定一个包含数字的数组,以下规则适用:

    • 0 删除所有以前的数字和所有随后的相邻偶数。
    • 1 删除所有先前的数字和所有后续的相邻奇数。
    • 如果数组的第一个元素是 1个 它可以被移除

    我试图写一个算法来减少数组,但我只能想出一个不好的解决方案:

    def compress(array)
      zero_or_one_index = array.rindex { |element| [0,1].include? element }
      array.slice!(0, zero_or_one_index) if zero_or_one_index
      deleting = true
      while deleting
        deleting = false
        array.each_with_index do |element, index|
          next if index.zero?
          previous_element = array[index - 1]
          if (previous_element == 0 && element.even?) || 
             (previous_element == 1 && element.odd?)
            array.delete_at(index)
            deleting = true
            break
          end
        end
      end
      array.shift if array[0] == 1
    end
    

    问题是 delete_if 类似地,如果我在数组上迭代时删除元素,就开始搞乱结果,因此我被迫使用while循环。

    示例:

    compress([3, 2, 0]) #=> [0]
    compress([2, 0, 4, 6, 7]) #=> [0,7]
    compress([2, 0, 4, 1, 3, 6]) #=> [6]
    compress([3, 2, 0, 4, 1, 3, 6, 8, 5]) #=> [6,8,5]
    

    这个问题出现在我正在cancancan上执行的一些重构的上下文中,以优化规则定义。

    1 回复  |  直到 6 年前
        1
  •  3
  •   engineersmnky    6 年前

    下面是我解决问题的方法:

    def compress(arr)
      return arr unless idx = arr.rindex {|e| e == 0 || e == 1}
      value = arr[idx]
      method_options = [:even?,:odd?]
      arr[idx..-1].drop_while do |n| 
        n.public_send(method_options[value])
      end.tap {|a| a.unshift(value) if value.zero? }
    end
    

    首先,我们使用 Array#rindex 是的。如果没有,则返回 Array 是的。

    然后我们得到这个指数的值。

    然后我们用 Array#[] 切下 阵列 从索引开始。

    然后删除所有相邻的 :even? :odd? 对应于 value ( 0 1 )使用 Array#drop_while 是的。

    最后如果 价值 我们把它放回 阵列 回来之前。

    实例

    compress([3, 2, 0]) 
    #=> [0]
    compress([2, 0, 4, 6, 7]) 
    #=> [0,7]
    compress([2, 0, 4, 1, 3, 6]) 
    #=> [6]
    compress([3, 2, 0, 4, 1, 3, 6, 8, 5]) 
    #=> [6,8,5]
    compress([4, 5, 6])
    #=> [4,5,6]
    compress([0])
    #=> [0]
    compress([1])
    #=> []
    

    如果你的目标像你的问题和要点所暗示的那样是变异的,我真的不会改变我所拥有的东西,而是去做:

    def compress!(arr)
      arr.replace(compress(arr))
    end
    

    例如

    a = [3, 2, 0, 4, 1, 3, 6, 8, 5]
    a == compress!(a)
    #=> true
    a 
    #=> [6,8,5]