2014-01-13 2 views
3

Я хотел бы группировать значения в одном массиве на основе близости значений и в соответствии с заданным интервалом между значениями.Аналогичные значения Group_by - Ruby

a=[1,2,5,7,20,25,50,53] 

интервал 5, например:

a=[[1,2,5,7],[20,25],[50,53]] 

если изменить интервал до 2:

a=[[1,2],[5,7],[20],[25],[50],[53]] 

Ive пытался решить эту проблему с помощью group_by однако без успеха.

Благодаря

+0

Может быть группа основана на 'мод interval'? –

+0

Итак, 1 находится в группе 7 в первом примере (7-1 - 6), потому что она близка к 2, которая близка к 7? – nurettin

ответ

1

Я думаю, что это будет делать эту работу, даже если есть, вероятно, является более хорошим решением (как всегда в Ruby):

def group array, diff 
    array.sort! # To remove if you're sure your array will always be sorted 
    # array = array.sort # could be a better solution if you don't want your array to be modified in place 
    res = [] 
    subres = [] 

    array.each do |elt| 
    if subres.count == 0 || elt - subres.last <= diff 
     subres << elt 
    else 
     res << subres 
     subres = [elt] 
    end 
    end 
    res << subres unless subres.empty? 
    res 
end 

a = [1, 2, 5, 7, 20, 25, 50, 53] 

p group a, 5 
p group a, 2 

выход будет

[[1, 2, 5, 7], [20, 25], [50, 53]] 
[[1, 2], [5, 7], [20], [25], [50], [53]] 

как вы разыскивается.

+0

Спасибо, Джерска. Именно то, что мне нужно. – AndreiR

2

Использование Enumerable#slice_before:

def group(a, n) 
    prev = a.first 
    a.slice_before { |x| 
    (x - prev > n).tap { prev = x } 
    }.to_a 
end 

a = [1,2,5,7,20,25,50,53] 
group(a, 5) # => [[1, 2, 5, 7], [20, 25], [50, 53]] 
group(a, 2) # => [[1, 2], [5, 7], [20], [25], [50], [53]] 
+0

Спасибо falsetru. Хороший. – AndreiR

0
def group(array, interval) 
    result = [[array[0]]] 
    array.inject do |x, y| 
    if y - x <= interval 
     result.last << y 
     else 
     result << [y] 
    end 
    y 
    end 
    result 
end 

a=[1,2,5,7,20,25,50,53] 

p group(a, 5) # => [[1, 2, 5, 7], [20, 25], [50, 53]] 
p group(a, 2) # => [[1, 2], [5, 7], [20], [25], [50], [53]] 
+0

Если вы используете 'result [-1]' или 'result.last', вам не нужно отслеживать' count'. – falsetru

+0

Ах, очень верно! В любом случае, ваш ответ настолько короче, но я признаюсь, что все еще пытаюсь обнять его. Я не был знаком ни с #slice_before, ни с #tap. – Kal

+0

Спасибо Kal. Я тоже. Не знал о slice_before. – AndreiR

Смежные вопросы