分组有两个参数。按指标分组 - "关闭"

时间:2016-04-09 17:58:14

标签: ruby

ruby​​中是否有办法使用指定的指标(非欧几里德)对数组进行分组?我知道有方法Enumerable#group_by。不幸的是,我只能给它一个论点。我希望它能够使用以下内容对项目进行分组:

items.group_by do |x,y|
  some_metric(x,y) < 1.23       # the two items are 'close'
end

如何处理这样的事情?

假设我有物品:

[['a', 'b'], 
 ['c', 'd'], 
 ['e','f'], 
 ['a', 'b', 'c'], 
 ['c', 'd', 'z'],
 ['a', 'b', 'k']]

我有一个指标告诉我两个数组是如何相同的。 ['a','b']['a', 'b', 'c']数组应该比['a', 'b']['e', 'f']更接近。 所以理想的输出就像是:

[
  [['a', 'b'], ['a', 'b', 'c'], ['a', 'b', 'k'],
  [['c', 'd'], ['c', 'd', 'z']],
  [['e','f']]
]

1 个答案:

答案 0 :(得分:0)

你可以通过将一个块传递给group_by来完全做到这一点。

arr = [[1,2],[3,4],[2,2],[6,8]]
arr.group_by{|f,s| f%2==0 && s%2==0}

这里的arr是一组数字元组。使用group_by我们检查每个元组以查看两个数字是否均匀。你也可以传递一个函数。

arr.group_by{|f,s| some_function(f,s)} 

更具体的例子是:

def proximity(arr)
  alpha = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
  dis_arr = []
  arr.each_with_index do |e,i|
    if i+1 < arr.length
      dis =  alpha.find_index(e) - alpha.find_index(arr[i+1])
      dis_arr << dis.abs
    end
  end
  dis_arr.inject{ |sum, el| sum + el }.to_f / arr.size
end

test = 
 [['a', 'b'], 
  ['c', 'd'], 
  ['e','f'], 
  ['a', 'b', 'c'], 
  ['c', 'd', 'z'],
  ['a', 'b', 'k']]

test.group_by{|arr| proximity(arr)}

返回:

{ 0.5 => [ 
    ["a","b" ],["c","d"],["e","f"]
  ],
  0.6666666666666666 => [
    [ "a","b","c"]],
  7.666666666666667 => [
    ["c","d","z"]
  ],
  3.3333333333333335 => [
    ["a","b","k"]
  ]
}

这不是您想要的,但.group_by会返回哈希值。将其转换为阵列以满足您的需求并不难。