【问题标题】:Learn Ruby the Hard Way ex39: return -1, key, defaultLearn Ruby the Hard Way ex39: return -1, key, default
【发布时间】:2014-08-20 20:51:49
【问题描述】:

所以我正在做 Learn Ruby the Hard Way 练习,结果卡在了一条线上。尝试谷歌搜索,甚至在 Python 课程中寻找答案。但找不到答案。

我的问题是:为什么Dict.get_slot有这行(它是干什么用的?):return -1, key, default
原练习在这里: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

【问题讨论】:

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


    【解决方案1】:

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

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

    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'],
    ]
    

    数组的第一个元素是真正的键转换成的整数,第二个元素是值。

    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 中找到 key,即 key 等于其中一个子数组的第一个元素,则执行第一个 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
    

    如果你不能指定默认值,那么当在 Hash 中查找一个不存在的键时会返回 nil,结果如下:

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

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

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

    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
    

    当散列中还不存在键时,results[key] 将返回 nil,并且您不能将 val 推入 nil。再一次,您可以通过测试 nil 来解决这个问题,然后创建一个值为新数组的新键,然后将 val 推入新数组。

    【讨论】:

    • 我只是不明白为什么 -1 和默认值在那里。 -1 的索引是调用数组的最后一个元素,对吗?
    • @abarro,在我的回答中查看我对您的评论的回复。
    猜你喜欢
    • 2015-06-01
    • 2014-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-25
    相关资源
    最近更新 更多