2013-07-17 3 views
2

я хэш, скажем:Как получить хэш от другого хэша, если ключи присутствуют в массиве

hash1 ={1=>"a",2=>"b",3=>"c",4=>"d"} 

и массив, скажем:

arr=[2,3] 

, и я должен найти результирующий хэш, как:

hash2={2="b",3=>"c"} 

То есть, в результате хэш должен содержать только те пары ключ-значение, чьи ключи присутствуют в данном массиве. Можно ли сделать это без цикла?

+0

Re: «без петли»: Почему вы не можете использовать петлю? – ruakh

+0

@ruakh - Я предполагаю, что это потому, что цикл кажется слишком многословным для простой задачи, подобной этой. (Кажется, должен быть более сжатый синтаксис на языке высокого уровня, таком как Ruby.) – DaoWen

ответ

2

Вы ищете что-то в этом роде?

1.9.3p392 :001 > hash1 ={1=>"a",2=>"b",3=>"c",4=>"d"} 
=> {1=>"a", 2=>"b", 3=>"c", 4=>"d"} 
1.9.3p392 :002 > arr=[2,3] 
=> [2, 3] 
1.9.3p392 :003 > hash2 = hash1.keep_if{|key, value| arr.include?(key)} 
=> {2=>"b", 3=>"c"} 

Я знаю, что ты не сказал, не цикл, но это так же близко, как я мог бы получить

+0

Спасибо, что оставил приглашение таким, какое оно есть. Действительно легко читать. – oldergod

+0

То же самое: это изменит hash1, он удалит все другие пары значений ключа. Вставьте «dup», чтобы предотвратить это. –

7

Ниже будет делать то, что вы хотите, но разрушительно для оригинального hash1.

hash2 = hash1.keep_if {|k,v| arr.include? k} 

Ниже будет делать то, что вы хотите, но держит hash1, как это первоначально было.

hash2 = hash1.select {|k,v| arr.include? k} 
+0

Это изменит 'hash1', он удалит все другие пары значений ключа. Вставьте «dup», чтобы предотвратить это. –

+0

Хорошо, это изменяет hash1. Как указано в другом ответе, использование select сделает то же самое, но менее разрушительное. –

+0

Thats true, использование 'select' лучше, чем использование' dup.keep_if', если вам это нужно. Для некоторых приложений может оказаться полезным изменить исходный массив. –

4
hash1.select {|k,v| arr.member? k} # {2=>"b", 3=>"c"} 
+0

Это самое быстрое решение и не меняет оригинальный хэш, поэтому для меня это звучит как лучший. +1 –

+0

Я пойду также с этим решением. –

1

Benchmark для всех ответов до сих пор:

require 'fruity' 

hash1 = Hash[[*1..10000].zip[*1.10000]] 
arr = 1.upto(1000).select(&:odd?) 

compare do 
    keep_if_include do 
    hash2 = hash1.dup.keep_if {|k,v| arr.include? k} 
    end 

    values_at_zip do 
    hash2 = Hash[arr.zip(hash1.dup.values_at(*arr))] 
    end 

    select_member do 
    hash2 = hash1.dup.select {|k,v| arr.member? k} 
    end 
end 

Результаты:

Running each test 4096 times. Test will take about 17 seconds. 
select_member is faster than keep_if_include by 2x ± 0.1 
keep_if_include is faster than values_at_zip by 410x ± 100.0 
1

, если вы используете рельсы, попробуйте

hash2 = hash1.sliec(*arr) 

, если вы просто используете рубин, попробуйте это

hash2 = hash1.select {|k, v| arr.include?(k) } 
Смежные вопросы