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']]
]
答案 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
会返回哈希值。将其转换为阵列以满足您的需求并不难。