在范围数组中查找重叠并使用新的chunked范围构建新数组

时间:2012-01-30 02:57:15

标签: javascript ruby arrays range

理想情况下,我喜欢Ruby或Javascript中的解决方案。数组而不是javascript中的范围就可以了。

我喜欢输入,例如:

    [0..301, 230..268, 242..364, 574..579, 587..593]

    [0,301, 230,268, 242,364, 574,579, 587,593]

把它变成类似的东西:

    [0..230, 230..242, 242..268, 268..301, 301..364, 574..579, 587..593]

    [[0,230], [230,242, [242,268], [268,301], [301,364], [574,579, [587,593]]

任何帮助都会很棒。这种做法有所帮助,但并不完全,因为它提供了全范围而不是分块范围How do I summarize array of integers as an array of ranges?

3 个答案:

答案 0 :(得分:2)

这是一个红宝石解决方案:

ranges = [0..301, 230..268, 242..364, 574..579, 587..593]
endpoints = ranges.map{|r| [r.first, r.last]}.flatten.sort
values = ranges.map{|r| r.to_a}.reduce(:+)

new_ranges = []
endpoints.reduce do |x, y|
    r = Range.new(x,y);
    new_ranges << r if r.all?{|v| values.include? v}
    y
end

puts new_ranges

#0..230
#230..242
#242..268
#268..301
#301..364
#574..579
#587..593

答案 1 :(得分:1)

这是一个Javascript解决方案:

(function (inp) {
    var out = [];

    inp.reduce(function (a,b) {
        return a.concat(b);
    }).sort().forEach(function(v,k, flat) {
        if(!k) return;
        out.push([flat[k-1], v]);
    });

    console.log(out);
})([[0,301], [230,268], [242,364], [574,579], [587,593]]);

此解决方案仅适用于支持Javascript 1.8的浏览器。我必须调整你的输入才能兼容Javascript,因为jfriend00说,Javascript没有范围。

这是输出:

[ [ 0, 230 ],
  [ 230, 242 ],
  [ 242, 268 ],
  [ 268, 301 ],
  [ 301, 364 ],
  [ 364, 574 ],
  [ 574, 579 ],
  [ 579, 587 ],
  [ 587, 593 ] ]

答案 2 :(得分:1)

Ruby解决方案。

def f(a)
  a.map! {|r| [r.first, r.last ] }.sort!

  segs = [a.shift]
  a.each {|s, e|
    if segs.last.last < s
      segs << [s, e]
    else
      segs.last.concat [s, e]
      segs.last.sort!
    end
  }
  segs.map {|seg|
    seg.each_cons(2).map { |s, e| (s..e) }
  }.flatten
end

puts f([0..301, 230..268, 242..364, 574..579, 587..593])

#0..230
#230..242
#242..268
#268..301
#301..364
#574..579
#587..593