如何找到数组项的区别

时间:2014-04-27 21:47:00

标签: ruby

如何找到数组["5 7", "2 2", "6 7", "10 4", "1 3", "6 7", "9 1", "7 8", "1 7", "4 6"]中两个连续项的差异。

输出应为[3,5],[ - 4,-5],[ - 4,3]等。

[3,5]来自[5-2,7-2]。

我有以下内容,但我不知道如何从这里开始。

["5 7", "2 2", "6 7", "10 4", "1 3", "6 7", "9 1", "7 8", "1 7", "4 6"]
.each_cons(2){|a| # need more here }

1 个答案:

答案 0 :(得分:3)

这是使用Ruby的Matrix课程的一种方法。下面我提到第二种不使用矩阵运算的方法,但我认为第一种方法更好。这两种方法都允许数组中的字符串包含两个以上的整数。

<强>代码

require 'matrix'

def diff(arr)    
  arr.map { |str| str.scan(/\d+/).map(&:to_i) }.each_cons(2).map { |e,f|
    (Matrix[e]-Matrix[f]).to_a }.flatten(1) 
end

示例

arr = ["5 7", "2 2", "6 7", "10 4", "1 3", "6 7", "9 1", "7 8", "1 7", "4 6"]
def diff(arr)
  #=> [[ 3, 5], [-4, -5], [-4, 3], [ 9, 1], [-5, -4],
  #    [-3, 6], [ 2, -7], [ 6, 1], [-3, 1]]

<强>解释

对于上面的示例,首先将字符串转换为包含两个整数的数组:

b = arr.map { |str| str.scan(/\d+/).map(&:to_i) }
  #=> [[5, 7],[2, 2],[6, 7],[10, 4],[1, 3],[6, 7],[9, 1],[7, 8],[1, 7],[4, 6]]

正如您所做的那样,使用Enumerable#each_cons处理每对数组:

c = b.each_cons(2)
  #=> #<Enumerator: [[5, 7], [2, 2], [6, 7], [10, 4], [1, 3],
  #    [6, 7], [9, 1], [7, 8], [1, 7], [4, 6]]:each_cons(2)>

要查看此枚举器的内容:

c.to_a
  #=> [[[ 5, 7], [2, 2]], [[2, 2], [6, 7]], [[6, 7], [10, 4]],
  #    [[10, 4], [1, 3]], [[1, 3], [6, 7]], [[6, 7], [ 9, 1]],
  #    [[ 9, 1], [7, 8]], [[7, 8], [1, 7]], [[1, 7], [ 4, 6]]]

将每一对映射到差异:

d = c.map { |e,f| (Matrix[e]-Matrix[f]).to_a }
  #=> [[[3, 5]], [[-4, -5]], [[-4, 3]], [[9, 1]], [[-5, -4]],
  #    [[-3, 6]], [[2, -7]], [[6, 1]], [[-3, 1]]]

最后,压平一个级别:

d.flatten(1) 
  #=> [[ 3, 5], [-4, -5], [-4, 3], [ 9, 1], [-5, -4],
  #    [-3, 6], [ 2, -7], [ 6, 1], [-3, 1]]

<强>替代

您不希望在map块中使用Matrix类,Array#transposeEnumerable#reduce(又名inject):

arr.map { |str| str.scan(/\d+/).map(&:to_i) }.each_cons(2).map { |e| 
      e.transpose.map { |a| a.reduce(&:-) } }