LINUX.ORG.RU

Ruby, хэши

 ,


1

2

Хочу в один ключ запихнуть два под-ключа:


h=Hash.new(:a=>"", :b=>"")

h[1][:a]="aaa"
h[1][:b]="bbb"

h[2][:a]="aaa222"
h[2][:b]="bbb222"

print h[1][:a]
print h[1][:b]

Выводится... правильно, aaa222 и bbb222. ЧЯДНТ?

★★★★

Неудивительно, что в Москву все поназжали, ведь сами жители ничего не умеют, кроме как запрещалкой махать.

anonymous
()

О сколько нам открытий чудных

[27] pry(main)> h=Hash.new("q")
=> {}
[28] pry(main)> h[:q]
=> "q"
[29] pry(main)> h[:q].upcase!
=> "Q"
[30] pry(main)> h[:q]
=> "Q"
[31] pry(main)> h[:h]
=> "Q"
Debasher ★★★★★
()

В этом конструкторе создается один дефолтный объект-заглушка. Проверь h[1].hash == h[2].hash, они одинаковы:

If obj is specified, this single object will be used for all default values.

Чтобы были разные, можно написать

h=Hash.new{|h,k| h[k] = {:a => '', :b => ''}}
cdshines ★★★★★
()
Ответ на: комментарий от anonymous

new → new_hash click to toggle source new(obj) → new_hash new {|hash, key| block } → new_hash

Returns a new, empty hash. If this hash is subsequently accessed by a key that doesn’t correspond to a hash entry, the value returned depends on the style of new used to create the hash. In the first form, the access returns nil. If obj is specified, this single object will be used for all default values. If a block is specified, it will be called with the hash object and the key, and should return the default value. It is the block’s responsibility to store the value in the hash if required.

При вызове new ты передаешь объект, в данном случае хеш (по сути, это значение по умолчанию). При попытке получить доступ по ключу, который не существует в хеше, возвращается переданный new объект.

h[1] — ключа 1 в хеше нет, возвращается объект { a: "", b: «» }, который ты модифицируешь. То же самое с h[2]. При каждой модификации новых пар ключ-значение в хеш не добавляется — ты модифицируешь лишь объект по умолчанию. Т.е. после всех модификаций хеш все так же пуст, как и раньше, однако значение по умолчанию в нем изменено.

При печати значения хеша ты опять передаешь ему несуществующий ключ, при этом возвращается модифицированное значение по умолчанию. Все логично.

Хочу в один ключ запихнуть два под-ключа

irb(main):029:0> h[:a][0] = "aaa"
=> "aaa"
irb(main):030:0> h[:b][0] = "bbb"
=> "bbb"
irb(main):031:0> h[:a][1] = "aaa222"
=> "aaa222"
irb(main):032:0> h[:b][1] = "bbb222"
=> "bbb222"
irb(main):033:0> h
=> {:a=>["aaa", "aaa222"], :b=>["bbb", "bbb222"]}
irb(main):034:0> 
theNamelessOne ★★★★★
()
Ответ на: комментарий от yu-boot

Можно написать более руби-вейно и аккуратно:

# где-то в начале:
initializer = ->(h,k){h[k]={:a => '', :b => ''}}
# где нужно:
hash = Hash.new &initializer

cdshines ★★★★★
()
Ответ на: комментарий от theNamelessOne

Т.е. фича только в порядке параметров? Потому что сам подход остался тем же, как я понимаю.

yu-boot ★★★★
() автор топика
Ответ на: комментарий от yu-boot

Т.е. фича только в порядке параметров?

Под ключами в хеше хранятся массивы. h[:a] — получаем массив под ключем :a, h[:a][1] — второй элемент в массиве, хранящимся под ключем :a.

theNamelessOne ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.