2010-10-21 23 views
9

Tengo una serie de números únicos. De esta manera: [1,2,3,4,7,8,10,12]. Puede ser sin clasificar. Lo que necesito es conseguir intevals para esta matriz:Ruby task: unión de números a intervalos

intervals_for [1,2,3,4,7,8,10,12] 
#=> "1-4, 7-8, 10,12" 

Tengo mi propia solución:

def intervals_for(array) 
    array.sort! 
    new_array = [] 
    array.each do |a| 
    if new_array.last and a == new_array.last.last+1 
     new_array.last << a 
    else 
     new_array << [a]  
    end 
    end 
    new_array.map{|a| a.size > 1 ? "#{a.first}-#{a.last}" : a.first}.join(", ") 
end 

Pero creo que por aquí es la solución más limpia

+0

Lo necesito para unirme años. Tengo varios años y quiero compactarlos de esta manera. Me gusta: 'Pedro Yanoviches (1985-1994, 1999-2010)' – fl00r

+0

posible duplicado de [Matriz de índices a una matriz de rangos] (http://stackoverflow.com/questions/3728660/array-of-indexes-to-array -of-ranges) –

+0

Tema muy cercano pero un poco diferente. De todos modos, es útil también. Gracias – fl00r

Respuesta

2

Esta es la mía, usando ver 1.9.1

def torange(a) 
    r=[];s=a[0] 
    a.uniq.sort!.each_cons(2) do |a| 
     r<<[s,a[0]] and s=a[1] if a[1]-a[0]!=1 
    end 
    left=a.index(s) 
    r<<[a[left..-1][0],a[left..-1][-1]] 
end 

torange([1,2,3,4,7,8,10,12]).each do |x| 
    puts x[0]==x[1] ? "#{x[0]}" : "#{x[0]}-#{x[1]}" 
end 

salida

$ ruby test.rb 
1-4 
7-8 
10 
12 
+0

La producción no es tan humana como lo necesito. Necesitamos un paso más para obtener esto aquí: '" 1-4, 7-8, 10, 12 "' – fl00r

+0

Gracias por el método 'each_cons' :) que es nuevo para mí – fl00r

+0

, la salida depende de usted para formatearlo de acuerdo a tu deseo ver mi edición – ghostdog74

0

Ésta es recursivo, se siente como que podría ser mejor aunque ...

arr = [1,2,3,4,7,8,10,12] 

def intervals(arr) 
    return arr if arr.size == 0 || arr.size == 1 

    int = [arr.shift] 
    while int.last + 1 == arr.first 
    int << arr.shift 
    end 

    (int.size == 1 ? int : ["#{int.first}-#{int.last}"]) + intervals(arr) 
end 

p intervals(arr) 
1

Aquí es mi sola línea:

array = [-10, -9, -1, 0, 1, 2, 3, 4, 10, 11, 15, 133] 
array.uniq.sort.inject([]){ |a, e| a[-1] && a[-1].last && a[-1].last == e-1 ? a[-1] = (a[-1].first..e) : a << (e..e); a } 
#=> [-10..-9, -1..4, 10..11, 15..15, 133..133] 

Y poco monkeypatchng

class Array 
    def.collect_to_ranges 
    self.uniq.sort.inject([]){ |a, e| a[-1] && a[-1].last && a[-1].last == e-1 ? a[-1] = (a[-1].first..e) : a << (e..e); a } 
    end 
end 

array = [1,2,3,4,5,6,7,8, 10] 
array.collect_to_ranges 
#=> [1..8, 10..10]