学习Ruby艰难的方法ex39:返回-1,键,默认

时间:2014-08-20 20:51:50

标签: ruby learn-ruby-the-hard-way

所以我正在做艰难学习Ruby 练习,并且卡在一条线上。尝试谷歌搜索,甚至在Python课程中寻找答案。但无法找到答案。

我的问题是:为什么 Dict.get_slot 有这一行(它的用途是什么?):返回-1,键,默认
原来的练习在这里:http://ruby.learncodethehardway.org/book/ex39.html

谢谢你们的家伙们!

module Dict
def Dict.new(num_buckets=256)
  # Initializes a Dict with the given number of buckets.
  aDict = []
  (0...num_buckets).each do |i|
    aDict.push([])
  end

  return aDict
end

def Dict.hash_key(aDict, key)
  # Given a key this will create a number and then convert it to
  # an index for the aDict's buckets.
  return key.hash % aDict.length
end

def Dict.get_bucket(aDict, key)
  # Given a key, find the bucket where it would go.
  bucket_id = Dict.hash_key(aDict, key)
  return aDict[bucket_id]
end

def Dict.get_slot(aDict, key, default=nil)
  # Returns the index, key, and value of a slot found in a bucket.
  bucket = Dict.get_bucket(aDict, key)

  bucket.each_with_index do |kv, i|
    k, v = kv
    if key == k
      return i, k, v
    end
  end

  return -1, key, default
end

def Dict.get(aDict, key, default=nil)
  # Gets the value in a bucket for the given key, or the default.
  i, k, v = Dict.get_slot(aDict, key, default=default)
  return v
end

def Dict.set(aDict, key, value)
  # Sets the key to the value, replacing any existing value.
  bucket = Dict.get_bucket(aDict, key)
  i, k, v = Dict.get_slot(aDict, key)

  if i >= 0
    bucket[i] = [key, value]
  else
    bucket.push([key, value])
  end
end

def Dict.delete(aDict, key)
  # Deletes the given key from the Dict.
  bucket = Dict.get_bucket(aDict, key)

  (0...bucket.length).each do |i|
    k, v = bucket[i]
    if key == k
      bucket.delete_at(i)
      break
    end
  end
end

def Dict.list(aDict)
  # Prints out what's in the Dict.
  aDict.each do |bucket|
    if bucket
      bucket.each {|k, v| puts k, v}
    end
  end
end
end

1 个答案:

答案 0 :(得分:1)

  

为什么Dict.get_slot有这一行(它的用途是什么?):return -1, key, default

这是一个返回三个值的数组的return语句。在执行return语句之前,ruby将替换变量key和default的值,然后ruby会将三个值收集到一个Array中并返回该数组。这是一个例子:

def dostuff
  key = 'a'
  default = 10
  return -1, key, default
end

p dostuff

--output:--
[-1, "a", 10]

正如评论所说:

# Returns the index, key, and value of a slot found in a bucket.

对评论的回应:

Dict是一个数组数组,例如:

[
  [200, 'hello'], 
  [210, 'world'],
]

数组的第一个元素是实际键已转换为的Integer,第二个元素是值。

Dict.get_slot()有两个可能的返回值:

  bucket.each_with_index do |kv, i|
    k, v = kv
    if key == k
      return i, k, v    #****HERE*****
    end
  end

  return -1, key, default  #*****OR HERE****

如果在Dict中找到了键,这意味着键等于其中一个子数组的第一个元素,则执行第一个return语句,并返回子数组的索引以及子阵列,即关键和价值。第二个return语句不会执行。

如果在Dict中找不到该键,则跳过第一个return语句并执行第二个return语句。在第二个return语句中,为子数组的索引返回-1。代码可能已被编写为返回nil,但在其他语言中,当搜索未在数组中找到元素时,通常返回-1;您从该方法的文档中知道,如果索引值为-1,则搜索结果为空。文档会说:

  

Dict.get_slot():返回一个三元素数组。第一个元素   返回数组是包含键的子数组的索引   如果没有子数组包含密钥,则返回-1;

对于默认值,ruby Hashes允许您指定在尝试检索不存在的键时返回的默认值(其他语言也提供该功能)。这允许你做这样的事情:

h = Hash.new(0)
h['a'] = 1
h['b'] = 2

target_keys =  %w[a b c]  #=>['a', 'b', 'c']  For people who are too lazy to type all those quote marks.

sum = 0
target_keys.each do |target_key|
  sum += h[target_key]
end

puts sum  #=>3

如果你不能指定默认值,那么当在哈希中查找不存在的键时会返回nil,这就是结果:

`+': nil can't be coerced into Fixnum (TypeError)

那是因为代码试图将nil添加到总和中。当然,您可以通过在执行添加之前测试h [target_key]是否为零来解决这个问题,但是能够指定默认值会使代码更简洁。

另一个更有用且非常常见的默认示例:

results = Hash.new { |this_hash, key| this_hash[key] = [] }

data = [
  ['a', 1],
  ['b', 2],
  ['a', 3],
  ['b', 4],
  ['c', 5],
]

data.each do |(key, val)|  #The parentheses cause the the subarray that is passed to the block to be exploded into its individual elements and assigned to the variables.
  results[key] << val
end

p results

--output:--
{"a"=>[1, 3], "b"=>[2, 4], "c"=>[5]}

如果您无法指定默认值,则以下行会导致错误:

results[key] << val

当密钥尚未存在于哈希中时,结果[key]将返回nil,并且您无法将val推送到nil。再一次,你可以通过测试nil然后创建一个新值,它的值是一个新数组,然后将val推入新数组来解决这个问题。