Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 如何确定一个数组是否包含另一个数组的所有元素_Ruby On Rails_Arrays_Ruby - Fatal编程技术网

Ruby on rails 如何确定一个数组是否包含另一个数组的所有元素

Ruby on rails 如何确定一个数组是否包含另一个数组的所有元素,ruby-on-rails,arrays,ruby,Ruby On Rails,Arrays,Ruby,鉴于: 我想确定它是否包含以下所有元素: a1 = [5, 1, 6, 14, 2, 8] 在这种情况下,结果为false 是否有任何内置的Ruby/Rails方法来识别这样的数组包含 实现这一点的一种方法是: a2 = [2, 6, 15] 有更好、更可读的方法吗?也许这更容易阅读: a2.index{ |x| !a1.include?(x) }.nil? 也可以使用阵列交点: a2.all? { |e| a1.include?(e) } 请注意,此处使用的size仅用于速度,您也可以

鉴于:

我想确定它是否包含以下所有元素:

a1 = [5, 1, 6, 14, 2, 8]
在这种情况下,结果为
false

是否有任何内置的Ruby/Rails方法来识别这样的数组包含

实现这一点的一种方法是:

a2 = [2, 6, 15]

有更好、更可读的方法吗?

也许这更容易阅读:

a2.index{ |x| !a1.include?(x) }.nil?
也可以使用阵列交点:

a2.all? { |e| a1.include?(e) }
请注意,此处使用的
size
仅用于速度,您也可以执行(较慢):


但我想第一个更具可读性。这3个是纯ruby(不是rails)。

这可以通过

(a1 & a2) == a1
这将创建两个数组的交集,返回
a2
中的所有元素,这些元素也位于
a1
中。如果结果与
a2
相同,则可以确保
a1
中包含所有元素


这种方法仅在
a2
中的所有元素首先彼此不同时才有效。如果出现双重情况,这种方法将失败。Tempos的方法仍然有效,因此我衷心推荐他的方法(也可能更快)。

如果没有重复的元素或者您不关心它们,那么您可以使用该类:

在幕后,这使用

a1 = Set.new [5, 1, 6, 14, 2, 8]
a2 = Set.new [2, 6, 15]
a1.subset?(a2)
=> false

根据你的数组有多大,你可以考虑一个高效的算法O(nlog n)


排序代价O(n logn),检查每对代价O(n),因此该算法是O(n logn)。使用未排序的数组,其他算法不能更快(渐进地)。

您可以对数组类进行monkey-patch:

def equal_a(a1, a2)
  a1sorted = a1.sort
  a2sorted = a2.sort
  return false if a1.length != a2.length
  0.upto(a1.length - 1) do 
    |i| return false if a1sorted[i] != a2sorted[i]
  end
end
试验

当然,该方法可以单独编写为标准方法,例如

irb(main):131:0> %w[a b c c].contains_all? %w[a b c]
=> true
irb(main):132:0> %w[a b c c].contains_all? %w[a b c c]
=> true
irb(main):133:0> %w[a b c c].contains_all? %w[a b c c c]
=> false
irb(main):134:0> %w[a b c c].contains_all? %w[a]
=> true
irb(main):135:0> %w[a b c c].contains_all? %w[x]
=> false
irb(main):136:0> %w[a b c c].contains_all? %w[]
=> true
irb(main):137:0> %w[a b c d].contains_all? %w[d c h]
=> false
irb(main):138:0> %w[a b c d].contains_all? %w[d b c]
=> true
你可以像这样调用它

def contains_all?(a,b)
    b.uniq.all? { |x| a.count(x) >= b.count(x) }
end
事实上,在分析之后,下面的版本速度更快,代码更短

contains_all?(%w[a b c c], %w[c c c])
如果两个数组中都有重复的元素,那么基于(a1-a2)或(a1&a2)的大多数答案都不起作用。我来到这里是想看看一个单词的所有字母(拆分成一个数组)是否都是一组字母的一部分(例如拼字)。这些答案都不管用,但这一个确实管用:

def contains_all?(a,b)
    b.all? { |x| a.count(x) >= b.count(x) }
end
def包含所有内容?(a1、a2)
try=1.chars.all?不信|

a1.count(letter)当我试图找出一个数组
[“a”、“b”、“c”]
是否包含另一个数组
[“a”、“b”]
时,就我而言,相同的顺序是这个问题的额外要求

以下是我的解决方案(我相信这是O(n)复杂性),适用于任何有额外需求的人:

def array_包括_array(array_to_inspect,array_to_search)
inspectLength=数组\u到\u inspect.length
searchLength=array\u to\u search\u for.length
如果searchLength==0,则
返回真值
结束
如果searchLength>inspectLength,则
返回错误
结束
缓冲区=[]
对于长度为0的i
buffer.push(数组到检查[i])
bufferLastIndex=buffer.length-1
如果(buffer[bufferLastIndex]!=数组搜索[bufferLastIndex]),则
缓冲区,清除
下一个
结束
如果(buffer.length==searchLength),则
返回真值
结束
结束
返回错误
结束
这将产生测试结果:

将“1:{array_包括_array([“a”,“b”,“c”],[“b”,“c”])}”置为true
将“2:{array_包括_array([“a”,“b”,“c”],[“a”,“b”])}”)置为true
将“3:{array_包括_array([“a”,“b”,“c”],[“b”,“b”])}”置为“false”
将“4:{array_包括_array([“a”,“b”,“c”],[“c”,“b”,“a”])}”置为“false”
将“5:{array_包括_array([“a”、“b”、“c”],[])}”)置为true
将“6:#{array_包括_array([],[“a”])}”置为“false”
将“7:#{array_包括_array([],[])}”置为true

这就是我们要走的路。它可能只是稍微缩短为
(a2-a1)。为空?
这只适用于集合数组,而不适用于具有集合的数组duplicates@Chris-您可以尝试使用Array#uniq。以霍尔格为例,它应该是
(a2.uniq-a1.uniq)。空?
就是我的意思。数组#unique将显式失败。使用
length
方法将执行得更好如果交集具有不同顺序的相同元素,则此方法将不起作用。当我试图回答这个问题时,我发现了这一点:后来我意识到很多聪明人已经在这里做到了@古巴很有趣。你有一些测试数据来重现这个吗?在我的测试中,结果数组似乎保留了第一个数组中元素的顺序(因此我最近对答案进行了编辑)。然而,如果事实并非如此,我想学习。@HolgerJust我犯了错误,做了(a1&a2)而不是(a2&a1),这就是我看到错误的原因。关于保留第一个数组的顺序,您是对的。您可以使用计数排序在O(n)中执行此操作。不,您不能。计数排序使用有限的范围,Ruby对大数的获取没有限制。您可以,因为您实际上不必对项进行排序-您只需要两个数组的哈希映射项-->计数,然后迭代键并比较计数。你确定数组#sort使用合并排序吗?如果使用OP对a1和a2的定义,并且a1“包含”a2的所有元素,我认为这应该是(a1和a2)。size==a2.size,因为a2是较小的数组,它应该包含较大数组中的所有元素(以获得“true”)-因此,如果两个数组中的所有元素都存在于较大数组中,则两个数组的交集应与较小数组的长度相同。可接受的答案(数组减法)是最快的解决方案。我在这里对它们进行了基准测试:
class Array
    def contains_all?(ary)
        ary.uniq.all? { |x| count(x) >= ary.count(x) }
    end
end
irb(main):131:0> %w[a b c c].contains_all? %w[a b c]
=> true
irb(main):132:0> %w[a b c c].contains_all? %w[a b c c]
=> true
irb(main):133:0> %w[a b c c].contains_all? %w[a b c c c]
=> false
irb(main):134:0> %w[a b c c].contains_all? %w[a]
=> true
irb(main):135:0> %w[a b c c].contains_all? %w[x]
=> false
irb(main):136:0> %w[a b c c].contains_all? %w[]
=> true
irb(main):137:0> %w[a b c d].contains_all? %w[d c h]
=> false
irb(main):138:0> %w[a b c d].contains_all? %w[d b c]
=> true
def contains_all?(a,b)
    b.uniq.all? { |x| a.count(x) >= b.count(x) }
end
contains_all?(%w[a b c c], %w[c c c])
def contains_all?(a,b)
    b.all? { |x| a.count(x) >= b.count(x) }
end
def contains_all?(a1, a2)
  try = a1.chars.all? do |letter|
    a1.count(letter) <= a2.count(letter)
  end
  return try
end