2010-10-21 24 views
9

Tôi có một dãy số uniq. Như thế này: [1,2,3,4,7,8,10,12]. Nó có thể được phân loại. Những gì tôi cần là để có được intevals cho mảng này:Tác vụ Ruby: nối các số vào khoảng thời gian

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

tôi đã có giải pháp của riêng tôi:

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 

Nhưng tôi nghĩ rằng ở đâu đó ở đây là giải pháp sạch hơn

+0

Tôi cần nó để tham gia các năm với nhau. Tôi có số năm và tôi muốn thu gọn chúng theo cách này. Giống như: 'Pedro Yanoviches (1985-1994, 1999-2010)' – fl00r

+0

có thể trùng lặp của [Mảng chỉ mục cho mảng phạm vi] (http://stackoverflow.com/questions/3728660/array-of-indexes-to-array phạm vi -of) –

+0

Chủ đề rất gần nhưng có một chút khác biệt. Dù sao nó cũng hữu ích. Cảm ơn bạn – fl00r

Trả lời

2

đây là của tôi, using 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 

output

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

Đầu ra không phải là nhân đạo như tôi cần. Chúng ta cần thêm một bước nữa để có được điều này ở đây: '" 1-4, 7-8, 10, 12 "' – fl00r

+0

Thanx cho phương thức 'each_cons' :) đó là mới đối với tôi – fl00r

+0

tốt, đầu ra là tùy thuộc vào bạn để định dạng nó theo mong muốn của bạn. xem chỉnh sửa của tôi. – ghostdog74

0

Đây là một đệ quy, cảm giác như nó có thể là tốt hơn mặc dù ...

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

Đây là của tôi một 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] 

Và ít 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] 
Các vấn đề liên quan