2015-07-09 2 views
0

В http://api.rubyonrails.org/classes/Hash.html#method-i-slice, я вижуRuby on Rails: более простой метод Hash.slice?

valid_keys = [:mass, :velocity, :time] 
search(options.slice(*valid_keys)) 

Я не получаю использование здесь. Я имею в виду, если я передаю array в slice, я определенно хочу, чтобы каждый key получил нарезок, то зачем использовать addtional * здесь?

Is можно превратить его в что-то вроде:

valid_keys = [:mass, :velocity, :time] 
search(options.simple_slice(valid_keys)) 

пути создания более простую версии slice?

+0

Вопрос о том, почему вам нужно спланировать массив для аргумента этого метода? Ссылка: [Хеш] (https://github.com/rails/rails/blob/b670fadb978c8a12c3414ed842cd49e4fde2cec0/activesupport/lib/active_support/core_ext/hash/slice.rb#L21) – vee

+0

@vee, ну, я действительно прочитал исходный код , хотя я не совсем понимаю это. Но основным условием является то, что я думаю, что «срез» должен выполнять грязную работу, я не уверен, правильно ли это мышление. – cqcn1991

ответ

3

Хэши могут иметь всевозможные вещи для ключей, ключи не обязательно должны быть просто строками или символами. Например, это вполне допустимо Hash:

{ [ :mass, :velocity, :time ] => 'pancakes' } 

Как Hash#slice должен знать, что иногда это:

h.slice([:mass, :velocity, :time]) 

означает «дать мне суб-хэш с этими тремя ключами», а иногда и его означает «дать мне суб-хэш с этим массивом в качестве ключа»?

Hash#slice принимает список ключей (один ключ на каждый аргумент), так что если вы хотите, чтобы ваши ключи в массиве, то вы должны восклицательный знак их в отдельные аргументы:

h.slice(*some_array_of_keys) 
# ------^ expand the array into individual arguments 

Вот почему вам нужно * ,

Если вы хотите, чтобы предположить, что ключи не будут массивы, то вы свободны сказать что-то вроде:

def simple_slice(*keys) # Allow any number of arguments 
    slice(*keys.flatten) # flatten all the arrays and then punt to Rails's slice. 
end 

Вы не можете придавить только один уровень (или, возможно, вы не) ,

+0

Я чувствую, что вы говорите, что 'array.flatten' такой же, как' * array'? Я в замешательстве? Они возвращают разные результаты при проверке на вопрос OP. И если 'simple_slice (* keys)' объявлен как таковой, это ничем не отличается от «active_support/core_ext/hash/slice.rb # Rails Rails», не так ли? – vee

+1

@vee: Нет, они очень разные. 'flatten' сглаживает все вложенные массивы (если они есть),' * array' используется для соответствия вариабельному поведению Hash # slice'. Попробуйте '{[1,2] => 3, [4,5] => 6} .slice ([1,2])' и '{[1,2] => 3, [4,5] => 6} .slice (1,2) ', и вы увидите разницу. –

1

Все возможно.

Вот оригинальный исходный код для Hash#slice, как показано на link from your question:

def slice(*keys) 
    keys.map! { |key| convert_key(key) } if respond_to?(:convert_key, true) 
    keys.each_with_object(self.class.new) { |k, hash| hash[k] = self[k] if has_key?(k) } 
end 

А вот как вы могли бы сделать это, чтобы спасти себя, что нажатие клавиши.

def simple_slice(keys) 
    keys.map! { |key| convert_key(key) } if respond_to?(:convert_key, true) 
    keys.each_with_object(self.class.new) { |k, hash| hash[k] = self[k] if has_key?(k) } 
end 

Очевидно, однако, такой simple_slice является менее гибким: первоначальный срез позволяет для произвольного количества ключей передаются в виде отдельных аргументов, например options.slice(:mass, :velocity, :time) в дополнение к разнесенной матрице options.slice(*valid_keys), но simple_slice будет поддерживать только массивы.

1

Вы должны восклицательный знак массив, передаваемый в качестве аргумента в #slice, потому что вы должны быть ясно, содержит ли массив список желаемых ключей или является нужный ключ. Почти все, включая Array, может быть хэш-ключом в рубине.

h = { 1 => "one", 2 => "two", [1,2] => "I'm an array!" } 
array = [1,2] 
h.slice(array) => {[1, 2]=>"I'm an array!"} 
h.slice(1,2) => {1=>"one", 2=>"two"} 
h.slice(*array) => {1=>"one", 2=>"two"} 

Оператор splat разрушает массив для использования в качестве нескольких аргументов, вместо того чтобы использовать его как один аргумент массива.

Смежные вопросы