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

Ruby中的一阶数组差异

  •  6
  • Peter  · 技术社区  · 16 年前

    最圆滑,最像红宝石的方法是什么?

    [1, 3, 10, 5].diff
    

    应该生产

    [2, 7, -5]
    

    即一阶差的数组。我已经想出了一个解决方案,我将在下面添加,但它需要Ruby1.9,而且并不是那么圆滑。还有什么可能?

    8 回复  |  直到 16 年前
        1
  •  2
  •   pierrotlefou    16 年前

    另一种方法……似乎是目前为止最短的方法:)

      module Enumerable
        def diff
            self[1..-1].zip(self).map {|x| x[0]-x[1]}
        end    
      end
    
        2
  •  5
  •   Jörg W Mittag    16 年前

    我喜欢这种功能风格:

    module Enumerable
      def diff
        each_cons(2).map {|pair| pair.reverse.reduce :-}
      end
    end
    

    编辑:我刚刚意识到 reverse 完全没有必要。如果这是一种函数式语言,我会使用模式匹配,但是Ruby不支持模式匹配。它 但是,支持破坏绑定,这对于模式匹配来说是一个很好的近似值。

    each_cons(2).map {|first, second| second - first}
    

    不过,没有笑脸。

    我喜欢你从左到右大声读出来的声音:“对每一对,应用第一和第二个元素的区别。”事实上,我通常不喜欢这个名字。 collect 更喜欢 map 相反,但在这种情况下,它读起来更好:

    each_cons(2).collect {|first, second| second - first}
    

    “对于每一对,收集其元素之间的差异。”听起来几乎像是一阶差异的定义。

        3
  •  2
  •   P Shved    16 年前

    当然,这个概念来自函数式编程:

    module Enumerable
      def diff
        self.inject([0]) { |r,x| r[-1] += x; r << -x } [1..-2]
      end
    end
    
    [1,3,10,5].diff
    

    注意,这里不需要任何单独的中间变量

        4
  •  2
  •   glenn mcdonald    16 年前

    这是我能找到的最快的方法(比目前所有其他人在1.8和1.9中的建议都快):

    module Enumerable
      def diff
        last=nil
        map do |x|
          r = last ? x - last : nil
          last = x
          r
        end.compact
      end
    end
    

    有了这个特写亚军:

    module Enumerable
      def diff
        r = []
        1.upto(size-1) {|i| r << self[i]-self[i-1]}
        r
      end
    end
    

    在这里的其他人中,testr自我描述的“虚弱”尝试是下一个最快的尝试,但是它仍然比这两种方法都慢。

    如果速度不是物体,我最喜欢的是:

    module Enumerable
      def diff!
        [-shift+first] + diff! rescue []
      end
    
      def diff
        dup.diff!
      end
    end
    

    但这(出于我不完全理解的原因)比这里的任何其他建议都要慢一个数量级!

        5
  •  2
  •   jes5199    16 年前

    J_¶RG W Mittag的微小变化:

    module Enumerable
      def diff
        each_cons(2).map{|a,b| b-a}
      end
    end
    
        6
  •  1
  •   Peter    16 年前
    # Attempt, requires ruby 1.9.
    module Enumerable
      def diff
        each_cons(2).with_object([]){|x,array| array << x[1] - x[0]}
      end
    end
    

    例子:

    [1,3,10,5].diff
    => [2, 7, -5]
    
        7
  •  0
  •   Gishu    16 年前

    另一种方法。

    module Enumerable
      def diff
        result = []
        each_with_index{ |x, i|
          return result if (i == (self.length-1))
          result << self[i+1] - x
        }
      end
    end
    
        8
  •  0
  •   testr    16 年前

    我无力的尝试…

    module Enumerable
      def diff
        na = []
        self.each_index { |x| r << self[x]-self[x-1] if x > 0 }
        na
      end
    end
    
    p [1,3,10,5].diff  #returned [2, 7, -5]
    
    推荐文章