0

そのため、Ruby を難しい方法で学習する演習を行っていて、1 行で行き詰まってしまいました。グーグルを試してみたり、Python のレッスンで答えを探したりしました。しかし、答えが見つかりませんでした。

私の質問は: Dict.get_slotこの行があるのはなぜですか(何のためにあるのでしょうか?): return -1, key, default

みんなありがとう!

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
4

1 に答える 1

1

Dict.get_slot にこの行があるのはなぜですか (何のためですか?):return -1, key, default

これは、3 つの値の配列を返す return ステートメントです。return ステートメントを実行する前に、ruby は変数 key と default の値を代入し、ruby は 3 つの値を配列にまとめて配列を返します。次に例を示します。

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

配列の最初の要素は実際のキーが変換された整数で、2 番目の要素は値です。

Dict.get_slot() には 2 つの可能な戻り値があります。

  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 で見つかった場合、つまりキーがサブ配列の 1 つの最初の要素と等しい場合、最初の return ステートメントが実行され、サブ配列のインデックスがサブ配列の要素と共に返されます。キーと値。2 番目の return ステートメントは実行されません。

キーが Dict に見つからない場合、最初の return ステートメントはスキップされ、2 番目の return ステートメントが実行されます。2 番目の return ステートメントでは、サブ配列のインデックスに対して -1 が返されます。代わりに nil を返すようにコードを記述することもできますが、他の言語では、検索で配列内の要素が見つからない場合に -1 を返すのが一般的です。そのメソッドのドキュメントから、インデックス値が -1 の場合、検索が空になることがわかります。ドキュメントは次のように言うでしょう:

Dict.get_slot(): 3 つの要素の配列を返します。返される配列の最初の要素は、キーを含む部分配列のインデックス、またはキーを含む部分配列がない場合は -1 です...

デフォルトに関しては、Ruby ハッシュを使用すると、存在しないキーを取得しようとしたときに返されるデフォルト値を指定できます (他の言語でもその機能が提供されています)。これにより、次のようなことができます。

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] が 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 を押し込むことで、これを回避できます。

于 2014-08-20T21:05:42.517 に答える