比较一个数组中的键与另一个数组

时间:2015-07-08 22:59:21

标签: arrays ruby hash

Ruby新手在这里。由于我的任务,我现在已经在两个小时的大部分时间里撞到了墙上。我要创建一个方法有两个参数 - 一个哈希和从该哈希键派生的键数组。如果Array具有散列中的所有键,则该方法应返回true,否则返回false。我必须确保hash参数中的每个键都包含在array_of_keys参数中。如果array_of_keys数组中的所有元素都在哈希参数中的键集内,则该方法应返回true,而不考虑特定顺序。赋值的编写者建议使用.sort方法来执行此操作。

这是我到目前为止所做的,但是我在解决如何对两个数组进行排序以进行比较时遇到了问题。

def do_i_have?(hash, array_of_keys)
  array_of_keys = []
  hash.each do |key, value|
    array_of_keys << key
  end
  hash.keys == array_of_keys
end

我也试过了,但没有运气。

def do_i_have?(hash, array_of_keys)
  array_of_keys = []
  hash.each do |key, value|
    array_of_keys << key
  end
  hash.keys.sort == array_of_keys.sort
end

为了对这两个数组进行排序和比较,正确的语法是什么?

谢谢你们!

当我使用第二种方法时,Rspec告诉我:

 do_i_have? returns true if all keys are in the hash
 do_i_have? returns true if all keys are in the hash, regardless of order

但是,

do_i_have? DOES NOT return false if it doesn't have any of the keys
do_i_have? DOES NOT return false if one or more of the keys isn't in the hash
do_i_have? DOES NOT return false if the hash has a different number of keys than the array

Rspec的:

describe "do_i_have?" do
  it "returns false if it doesn't have any of the keys" do
    h = { name: "Computer", cost: "$1,000" }
    keys = [:age, :bio]

    expect( do_i_have?(h, keys) ).to eq(false)
  end
  it "returns false if one or more of the keys isn't in the hash" do
    h = { name: "Computer", cost: "$1,000" }
    keys = [:name, :bio, :cost]

    expect( do_i_have?(h, keys) ).to eq(false)
  end
  it "returns false if the hash has a different number of keys than the array" do
    h = { name: "Computer", cost: "$1,000" }
    keys = [:name]

    expect( do_i_have?(h, keys) ).to eq(false)
  end  
  it "returns true if all keys are in the hash" do
    h = { name: "Computer", cost: "$1,000", uuid: "1234" }
    keys = [:name, :cost, :uuid]

    expect( do_i_have?(h, keys) ).to eq(true)
  end
  it "returns true if all keys are in the hash, regardless of order" do
    h = { name: "Computer", cost: "$1,000", uuid: "1234" }
    keys = [:name, :uuid, :cost]

    expect( do_i_have?(h, keys) ).to eq(true)
  end  
end

3 个答案:

答案 0 :(得分:1)

这感觉就像作弊,但为什么不呢......

$ cat foo.rb

def do_i_have?(hash, array_of_keys)
  hash.size == (hash.keys & array_of_keys).size
end

hash = {a: 1, b: 2, c: 3}

puts do_i_have?(hash, [:a, :b, :c])
puts do_i_have?(hash, [:c, :a, :b])
puts do_i_have?(hash, [:a, :b])

跑步时:

$ ruby foo.rb
true
true
false

无需对它们进行排序... hash.keys & array_of_keys将包含两个数组共有的所有字段(不包括重复项)。因此,如果它与散列中的键大小相同,那么它们必须是相同的集合,对吧?

答案 1 :(得分:1)

Hash有一个返回哈希键的数组的方法。如果您通过前一句中链接的Hash实例方法,您将找到该方法。它比你拥有的更容易(这是正确的,顺便说一下):

array_of_keys = []
hash.each do |key, value|
  array_of_keys << key
end

您的主要问题是比较两个数组,不是为了相等,而是为了具有相同的值,但不一定是相同的顺序。那是因为:

([1,2] == [2,1]) #=> false

有几种方法可以确定两个数组ab是否具有相同的元素。这是三个:

  • 排序ab,然后查看两个排序的数组是否相等。您需要使用方法Array#sort
  • 查看a中的每个元素是否在b中,b中的每个元素都在a中(提示:请考虑方法Array#-)。< / LI>
  • ab转换为Set,并确定这两组是否相等。 (要使用类Set的方法,您需要require 'set'。要将数组a转换为集合,您可以使用s = Set.new(a)

答案 2 :(得分:1)

哈希的密钥数组可以简单地由hash.keys生成。如果您对该数组进行排序并将其与您传入该方法的数组的排序版本进行比较,那么您应该很好:

def do_i_have?(hash, array)
  hash.keys.sort == array.sort
end