【问题标题】:How to find if one array is a subset of another array in Ruby?如何在Ruby中查找一个数组是否是另一个数组的子集?
【发布时间】:2018-04-28 06:14:22
【问题描述】:

最好在 Ruby 中

当顺序很重要时,我需要一种方法来确定一个数组是否是另一个数组的“子数组”

例如,

a = ["1", "4", "5", "7", "10"]
b = ["1", "4", "5"]
c = ["1", "5", "4"]
d = ["1", "5", "10"]

a includes b = true
a includes c = false
a include d = false

提前致谢。

【问题讨论】:

  • @ruakh 如果用户想用 Ruby 回答,这是重复的吗?
  • @ruakh 根据给出的测试用例中的示例,我认为这不是重复的。见stackoverflow.com/questions/26568560/…
  • 我不认为这是重复的,因为元素必须是连续的。
  • 我把它重新打开了。
  • @mudasobwa 不错。

标签: ruby algorithm collections


【解决方案1】:
[b, c, d].map do |arr|
  a.each_cons(arr.length).any?(&arr.method(:==))
end
#⇒ [true, false, false]

这绝对不是最高效的解决方案,但不是巨大的数组是可行的,重要的是,它是可读的。

Enumerable#each_cons.

【讨论】:

  • 我们可以使用a.each_cons(arr.length).include?(arr)来达到同样的效果吗?
【解决方案2】:
a = ["1", "4", "5", "7", "10"]
b = ["1", "4", "5"]
c = ["1", "5", "4"]
d = ["1", "5", "10"]


def sub_set?(arr_a, arr_b)
  arr_a.select.with_index do |a, index|
    arr_b[index] == a
  end == arr_b
end

puts "testing sub_set #{a.inspect} and #{c.inspect}"
puts sub_set?(a,c).inspect

【讨论】:

  • 您可以使用detect.with_index { |a, i| arr_b[i] != a } 而不是select 快速失败。
  • 现在完全不行了,应该是detect {...} ? false : true
  • @mudasobwa 我花了太多时间让你们重新打开这个问题,现在我累了。你的答案更好。我要去睡觉了。谢谢。
【解决方案3】:
class Array
  def includes(array)
    return false if array.size > self.size
    indexes = []
    self.each_with_index {|e, i| indexes << i if e == array[0]}
    p indexes
    indexes.each do |i|
      return true if self[i..i+array.size-1] == array
    end
    return false
  end
end

p a.includes b
p a.includes c
p a.includes d

或者更少 phpish :)

class Array
  def includes(array)
    return false if array.size > self.size
    indexes = each.with_index.select { |e, i| e == array[0] }.map(&:last)
    indexes.each {|i| self[i..i+array.size-1] == array ? (return true) : (return false)}
  end
end

p a.includes b
p a.includes c
p a.includes d

【讨论】:

  • indexes = select.with_index { |e, i| e == array[0] }.map(&amp;:last) 会少一些 phpish。
  • 啊,对不起,我的错,应该是indexes = each.with_index.select { |e, i| e == array[0] }.map(&amp;:last),因为如果selectwith_index 之前,它会选择普通元素。
  • 你真的发布了一个猴子补丁并且有两个版本只是方法名称不同吗?还有 4 个空格缩进?
【解决方案4】:

您可以join 带有任意字符的元素然后比较字符串:

a.join(' ').match?(array.join(' '))

这适用于您提供的测试用例:

a.join(' ').match?(b.join(' '))                                                                                                                     
 #=> true
a.join(' ').match?(c.join(' '))                                                                                                                     
 #=> false
a.join(' ').match?(d.join(' '))                                                                                                                   
 #=> false

但这不是一个通用的解决方案,并且会在不同类型的数组上失败(请参阅 cmets 以获得进一步讨论)。

【讨论】:

  • 如果数组包含非字符串,则会失败。该方法应该适用于任何数组值。
  • @lacostenycoder 好的,这可能不是一个健壮或通用的方法,但它可以在许多情况下使用(例如字符串数组或整数数组)。这可能足以满足 OP 的需求,因此值得一提作为答案。
  • @SagarPandya。我打算这样做,但我认为我会被猛烈抨击或投反对票,所以我试图找到不依赖字符串转换的东西。这种方法是简单的方法。我失眠了,很抱歉投了反对票。但也请参阅stackoverflow.com/questions/33174985/…,因为在我开始时它被标记为重复。进行一些编辑,我会反转它。
  • @lacostenycoder 是的,我只是在寻找一个厚颜无耻的捷径,但我应该在我的回答中提到它的缺点。您的反对票很好,您有正当理由。只有在没有给出或给出无效理由时,我才不喜欢投反对票。
  • 如果没有反对票,我可能不会赞成,但我认为反对票不值得,所以我赞成最多抵消其中的五个。我不认为缺乏稳健性是一个公平的反对意见,因为 OP 的示例表明所有数组元素都是字符串(数字)。
猜你喜欢
  • 2012-05-20
  • 2010-09-24
  • 2016-12-13
  • 1970-01-01
  • 1970-01-01
  • 2012-08-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多