【问题标题】:idiomatic way to check if array contains ordered (but possibly non-continuous) set of elements检查数组是否包含有序(但可能是不连续的)元素集的惯用方法
【发布时间】:2016-09-02 18:33:20
【问题描述】:

我想知道是否有更惯用的方法来获得下面代码所代表的功能。基本上我只想检查数组是否按照pattern 指定的顺序包含pattern 中的元素。这些元素之间有差距是可以的。

class Array
  def has_pattern?(pattern)
    offset = 0
    pattern.each do |p|
      offset = self[offset..-1].index(p)
      return false if offset.nil?
    end
    return true
  end
end

puts [1, 2, 3, 4, 5, 1].has_pattern?([1, 4, 5]) # true
puts [1, 2, 3, 4, 5, 1].has_pattern?([2, 3, 1]) # true
puts [1, 2, 3, 4, 5, 1].has_pattern?([1, 3, 2]) # false

上面的代码似乎可以工作,但对我来说不像是惯用的 Ruby。有没有更好的写法?

【问题讨论】:

  • 不是特别,不是。你写的算法很不错。我敢肯定还有其他方法可以做到这一点,但它们不会像你所拥有的那样有效。

标签: ruby


【解决方案1】:

这是我的看法:

class Array
  def has_pattern?(ptn)
    i = 0
    self.each do |elem|
      i += 1 if elem == ptn[i]
    end
    i >= ptn.size
  end
end

它只通过数组一次,所以当数组很大时可能会有所不同。

【讨论】:

  • 这具有修改调用者(通过引用)传递的模式对象的潜在不良副作用。
【解决方案2】:

这是一种不同的处理方式:

class Array
  def has_pattern?(pattern)
    (self - (self - pattern))
      .each_cons(pattern.length)
      .any? { |p| p === pattern }
  end
end

但是,正如我在上面的 cmets 中所说,我认为您的解决方案是优越的。

【讨论】:

  • 它给[1,2,2,2,3].has_pattern? [1,2,3]的答案不正确
  • @michau 啊,那些讨厌的集合运算符和他们去重复的倾向。让我看看我能不能解决它。
  • @michau Hrrm,你确定吗?我显示它返回错误,我认为根据 OP 是正确的。
  • 数组包含1、2、3,按这个顺序(有间隔)。为什么要返回 false?
  • 啊,前辈。接得好。我认为在 set 操作之后将 uniq 放在那里可以解决这个问题,但是它不能采用重复的模式。这可能只是一个糟糕的解决方案。
猜你喜欢
  • 2018-04-22
  • 2018-06-15
  • 2017-07-03
  • 2019-08-24
  • 2016-10-13
  • 2019-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多