所以我正在做艰难学习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
答案 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推入新数组来解决这个问题。