【问题标题】:comparing keys in one array with another比较一个数组中的键与另一个
【发布时间】:2015-07-09 08:09:38
【问题描述】:

Ruby 新手在这里。由于我有一项任务,我现在已经有两个小时的大部分时间把头靠在墙上了。我要创建的方法有两个参数——一个哈希和从该哈希的键派生的键数组。如果 Array 包含散列中的所有键,则该方法应返回 true,否则返回 false。我必须确保 hash 参数中的每个键也包含在 array_of_keys 参数中。如果 array_of_keys 数组中的所有元素都在 hash 参数的键集中,则该方法应该返回 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

【问题讨论】:

  • 您的方法应该被赋予键数组,还是应该生成和验证数组(如您所显示的)?此外,您可以简单地使用 hash.keys 从哈希中获取键数组。您应该浏览 Ruby Hash 和 Ruby Array 的类文档以获取可用方法。最后,数组是 ordered 的,所以顺序很重要(这就是为什么您的第一次尝试通常不起作用的原因)。我运行了你的第二种方法,它返回“真实”,所以它似乎有效。
  • 该方法应该从散列中的键生成数组,然后验证该数组是否具有散列中的所有键。是的,我知道 hash.keys 会以特定顺序为您提供哈希键的数组。但是,我需要对 array_of_keys 和 hash.keys 进行排序,以便可以比较它们,并且我可以得到真或假的结果。但是,我的第二种方法没有通过通过作业所需的测试。
  • 您可以编辑您的提交以包含您的测试套件吗?
  • 如果您需要对它们进行排序,您仍然可以使用hash.keys.sort。我仍然不明白为什么需要hash.each 循环。如果你想使用循环,你可以使用hash.each_key do |key|,因为你没有使用这个值。但是这两种方法都不能保证键的顺序,因为 Ruby 不会将哈希的键保持为有序集合。
  • @vikram7 我目前正在学习一门课程,因此所有练习都在浏览器中完成,但我已将测试告诉我的内容添加到原始提交中。

标签: arrays ruby hash


【解决方案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 &amp; array_of_keys 将包含两个数组共有的所有字段(不包括重复项)。所以如果它与哈希中的键大小相同,那么它们必须是相同的集合,对吧?

【讨论】:

  • 这几乎满足了我的作业要求,但我的测试表明do_i_have? DOES NOT return false if one or more of the keys isn't in the hash
  • 啊,我错过了这个要求。我会留给你调整以处理这种情况:)
【解决方案2】:

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#- 方法)。
  • ab转换为Sets,判断这两组是否相等。 (要使用 Set 类的方法,您需要 require 'set'。要将数组 a 转换为集合,您可以使用 s = Set.new(a)

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

    • 数组中的重复项呢?不知道这对 OP 是好是坏,但可能是个问题。
    猜你喜欢
    • 2022-06-27
    • 1970-01-01
    • 1970-01-01
    • 2021-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-12
    • 1970-01-01
    相关资源
    最近更新 更多