代码之家  ›  专栏  ›  技术社区  ›  chris

(ruby)如何检查一个范围是否包含另一个范围的子集?

  •  16
  • chris  · 技术社区  · 16 年前

    如果我有两个重叠的范围:

    x = 1..10
    y = 5..15
    

    当我说:

    puts x.include? y 
    

    输出是:

    false 
    

    因为这两个范围只是部分重叠。

    但是,如果我想要它是“真的”,当两个范围之间有部分重叠时,我该怎么写呢?换句话说,我需要一种方法来知道一个范围何时包含另一个范围的子集。我认为用Ruby写这个有一种优雅的方式,但是我能想到的唯一解决方案是冗长的。

    9 回复  |  直到 8 年前
        1
  •  7
  •   ski    15 年前

    在大范围内使用时要小心,但这是一种优雅的方法:

    (x.to_a & y.to_a).empty?
    
        2
  •  59
  •   MarkusQ    16 年前

    有效的方法是比较极限

    (x.first <= y.last) and (y.first <= x.last)
    
        3
  •  2
  •   Abe Voelker    14 年前

    您还可以将范围转换为 sets 因为你基本上是在这里做集合交集。如果处理的范围超过两个,可能会更容易。

    x = (1..10).to_set
    y = (5..15).to_set
    !(x & y).empty? #returns true (true == overlap, false == no overlap)
    
        4
  •  2
  •   Khaja Minhajuddin    13 年前

    该方法可以有效地测试多个范围之间的重叠:

    def range_overlap?(ranges)
      sorted_ranges = ranges.sort
      sorted_ranges.each_cons(2).each do |r1, r2|
        return true if r2.first <= r1.last
      end
      return false
    end
    
    
    def test(r)
      puts r.inspect, range_overlap?(r)
      puts '================'
      r = r.reverse
      puts r.inspect, range_overlap?(r)
      puts '================'
    end
    
    
    test [[1,9], [10, 33]]
    test [[1,10], [5, 8]]
    test [[1,10], [10, 33]]
    
        5
  •  1
  •   Evgeny Zislis    16 年前

    如果一个范围包括第二个范围的开始或结束,那么它们会重叠。

    (x === y.first) or (x === y.last)
    

    与此相同:

    x.include?(y.first) or x.include?(y.last)
    
        6
  •  1
  •   Soleone    16 年前

    但如果我想让它是“真的”,当两个范围之间有部分重叠时, 我该怎么写?

    可以将范围转换为数组,并使用 & 操作员( 连词) . 这将返回一个新数组,其中所有元素都出现在这两个数组中。如果结果数组不是空的,这意味着存在一些重叠元素:

    def overlap?(range_1, range_2)
      !(range_1.to_a & range_2.to_a).empty?
    end
    
        7
  •  1
  •   Xiong Chiamiov    16 年前

    如果你在检查重叠,我就这么做。

    (x.include? y.first) or (x.include? y.last)
    

    因为一个范围必须包括另一个范围的至少一端。对我来说,这比公认的共轭答案更直观,尽管不如Markusq的极限比较那么有效。

        8
  •  0
  •   Dorian    8 年前

    铁轨有 Range#overlaps?

    def overlaps?(other)
      cover?(other.first) || other.cover?(first)
    end
    
        9
  •  -1
  •   pguardiario    13 年前

    一些有用的可枚举方法:

    # x is a 'subset' of y
    x.all?{|n| y.include? n}
    # x and y overlap
    x.any?{|n| y.include? n}
    # x and y do not overlap
    x.none?{|n| y.include? n}
    # x and y overlap one time
    x.one?{|n| y.include? n}