比较Ruby中的序列

时间:2011-08-09 09:13:27

标签: ruby arrays compare

假设我必须(小到中等)数组:

tokens = ["aaa", "ccc", "xxx", "bbb", "ccc", "yyy", "zzz"]
template = ["aaa", "bbb", "ccc"]

如何确定tokens是否包含同一订单中template的所有条目?

(请注意,在上面的示例中,应忽略第一个“ccc”,导致由于最后一个“ccc”而匹配。)

6 个答案:

答案 0 :(得分:3)

这适用于您的样本数据。

tokens = ["aaa", "ccc", "xxx", "bbb", "ccc", "yyy", "zzz"]
template = ["aaa", "bbb", "ccc"]

pos = 0
condition_met = true
template.each do |temp|
  if (tpos = tokens[pos..-1].index temp) == nil then
    break condition_met = false
  else
    pos = tpos
  end
end

puts condition_met

答案 1 :(得分:2)

这是单线条件:

 tokens.select {|t| t if template.include?(t)}.reverse.uniq == template.reverse \
  or \
   tokens.select {|t| t if template.include?(t)}.uniq == template

示例:

def check_order(tokens, template)
   tokens.select {|t| t if template.include?(t)}.reverse.uniq == template.reverse \
    or \
     tokens.select {|t| t if template.include?(t)}.uniq == template
end

tokens = ["aaa", "xxx", "bbb", "ccc", "yyy", "zzz"]
template = ["bbb", "aaa", "ccc"]
check_order(tokens,template) # => false

tokens = ["aaa", "ccc", "xxx", "bbb", "ccc", "yyy", "zzz"]
template = ["aaa", "bbb", "ccc"]
check_order(tokens,template) # => true

tokens = ["aaa", "ccc", "xxx", "bbb", "ccc", "yyy", "zzz"]
template = ["aaa", "ccc", "bbb"]
check_order(tokens,template) # => true

答案 2 :(得分:2)

manatwork提供的解决方案很好,但是对我来说这是一个看起来更像红宝石的解决方案:

tokens = ["aaa", "ccc", "xxx", "bbb", "ccc", "yyy", "zzz"]
template = ["aaa", "bbb", "ccc"]

def tokens_include_template(tokens, template)
  tokens = tokens.to_enum
  template.each do |t|
    return false unless loop { break true if t == tokens.next }
  end
  true
end

puts tokens_include_template(tokens, template)

答案 3 :(得分:2)

我认为最干净的是通过递归来做到这一点:

class Array
  def align(other)
    if pos = index(other.first)
      other.size == 1 || slice(pos..-1).align(other.drop(1))
    end
  end
end

这样:

[1,2,3,4,3,2,1].align([1,2,3])
=> true
[1,2,3,4,3,2,1].align([1,4,1])
=> true
[1,2,3,4,3,2,1].align([1,4,2,3])
=> nil

答案 4 :(得分:1)

这是另一个想法,如果阵列是中小型的,它可能工作正常。 它只是将标记转换为正则表达式并尝试将模板与其匹配。 (这也会将空模板视为与令牌匹配,因此如果您不想这样,只需明确处理此角点)

def tokens_in_template? tokens, *template
  re = /^#{tokens.map {|x| "(?:#{x})?"}.join}$/
  !! (template.join =~ re)
end

tokens = ["aaa", "ccc", "xxx", "bbb", "ccc", "yyy", "zzz"]
puts tokens_in_template? tokens                            # => true
puts tokens_in_template? tokens, "aaa", "bbb", "ccc"       # => true
puts tokens_in_template? tokens, "aaa", "bbb", "ccc", "aa" # => false
puts tokens_in_template? tokens, "aaa", "zzz", "ccc"       # => false
puts tokens_in_template? tokens, "aaa", "zzz"              # => true

答案 5 :(得分:0)

如果结果为空,只需从第二个数组中减去第一个数组即可得到匹配

result = template - tokens
if result.empty?
  #You have a match
else
  #No match
end

在此处阅读有关数组的更多信息http://www.ruby-doc.org/core/classes/Array.html#M000273

如果订单很重要,请使用< =>操作员再次在上面的链接中描述