2010-10-21 11 views
9

Ho una serie di numeri uniq. Così: [1,2,3,4,7,8,10,12]. Può essere non ordinato. Che cosa ho bisogno è quello di ottenere intevals per questa matrice:Attività rubino: unione di numeri a intervalli

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

ho la mia propria soluzione:

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 

Ma credo che da qualche parte qui è la soluzione più pulita

+0

Ne ho bisogno per unirmi agli anni insieme. Ho un numero di anni e voglio compattarli in questo modo. Ad esempio: 'Pedro Yanoviches (1985-1994, 1999-2010)' – fl00r

+0

possibile duplicato di [Matrice di indici a serie di intervalli] (http://stackoverflow.com/questions/3728660/array-of-indexes-to-array -of-range) –

+0

Tema molto vicino ma un po 'diverso. Comunque è utile anche. Grazie – fl00r

risposta

2

qui è mio, utilizzando 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 

uscita

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

L'output non è così umano come ho bisogno. Abbiamo bisogno di un ulteriore passaggio per ottenere questo qui: '" 1-4, 7-8, 10, 12 "' – fl00r

+0

Grazie per il metodo 'each_cons' :) questo è nuovo per me – fl00r

+0

beh, l'output dipende da te per formattarlo secondo il tuo desiderio. vedi la mia modifica. – ghostdog74

0

Questo è ricorsivo, si sente come potrebbe essere meglio però ...

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

Ecco il mio one-liner:

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] 

E 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] 
Problemi correlati