How do I summarize array of integers as an array of ranges?

后端 未结 5 2176
-上瘾入骨i
-上瘾入骨i 2020-12-16 02:48

I\'d like to take input such as:

[1,2,4,5,6,7,9,13]

and turn it into something like the following:

[[1,2],[4,7],[9,9],[13,1         


        
相关标签:
5条回答
  • 2020-12-16 03:09

    Hmm, well, it's not tokland's masterpiece, but I think it may be a good straightforward solution...

    [1,2,4,5,6,7,9,13].inject([]) do |m, v|
      if m.last.to_a.last == v.pred
        m[-1][-1] = v
      else
        m << [v, v]
      end
      m
    end
    
    0 讨论(0)
  • 2020-12-16 03:12

    An even easier solution than @tokland's very nice one is using chunk_while:

    xs.chunk_while { |a, b| a + 1 == b }.map do |seq|
      [seq.first, seq.last]
    end
    

    Note: chunk_while was introduced in Ruby 2.3

    0 讨论(0)
  • 2020-12-16 03:16

    Functional approach using Enumerable#chunk:

    ranges = [1, 2, 4, 5, 6, 7, 9, 13]
      .enum_for(:chunk) # .chunk for Ruby >= 2.4
      .with_index { |x, idx| x - idx }
      .map { |_diff, group| [group.first, group.last] }
    
    #=> [[1, 2], [4, 7], [9, 9], [13, 13]]
    

    How it works: once indexed, consecutive elements in the array have the same x - idx, so we use that value to chunk (grouping of consecutive items) the input array. Finally we just need to take the first and last elements of each group to build the pairs.

    0 讨论(0)
  • 2020-12-16 03:19

    Another approach

    def summarize(x)
      x.inject([]) do |acc, value|
        if acc.last && acc.last[1] + 1 == value
          acc.last[1] = value
          acc
        else
          acc << [value,value]
        end
      end
    end
    

    Similar to Larsenal's method but using inject to manage the boring stuff.

    0 讨论(0)
  • 2020-12-16 03:27

    This is almost straight from the enumerable#slice_before method documentation:

    ar = [1,2,4,5,6,7,9,13]
    prev = ar[0]
    ar.slice_before{|e|prev,prev2 = e,prev; prev2.succ != e}.map{|a|a.first..a.last}
    #=> [1..2, 4..7, 9..9, 13..13]
    

    This should work with characters, dates, anything with a .succ method.

    0 讨论(0)
提交回复
热议问题