2012-06-12 2 views
1

Учитывая хэшПоиск массив хэшей с частичной Hash в Рубине

z = [{'a' => 1, 'b' => 2}, {'a' => 3, 'b' => 4}, {'a' => 1, 'b' => 4}] 

Как найти, если сам параметр поиска является хэш, например

{'a' => 3} 

так, что я могу сделать что-то вроде z.find_by_hash ({ 'а' => 3}) для того, чтобы вернуть

{'a' => 3, 'b' => 4} 

, а также получить коллекцию массивов, как z.find_by_hash ({ 'а' => 1}) для того, чтобы вернуть

[{'a' => 1, 'b' => 2}, {'a' => 1, 'b => 4}] 

Благодарности

ответ

1

Вы можете сделать это:

class Array 
    def find_by_hash(hash) 
    self.select { |h| h.includes_hash?(hash) } 
    end 
end 

class Hash 
    def includes_hash?(other) 
    included = true 

    other.each do |key, value| 
     included &= self[key] == other[key] 
    end 

    included 
    end 
end 

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

ary = [ {:a => 1, :b => 3, :c => 5}, {:a => 5, :b => 2, :c => 8} ] 
ary.find_by_hash({ :a => 1, :c => 5 }) 

Примечание: Вы должны также рассмотреть возможность использования Symbol с для Hash ключей, так как это является обычной практикой в ​​Ruby, но мой подход также работает с вашими ключами.

+0

Спасибо. Это правильно, поскольку в нем рассматривается основная проблема поиска хэша в хеше – globetrotter

0
z = [{'a' => 1, 'b' => 2}, {'a' => 3, 'b' => 4}, {'a' => 1, 'b' => 4}] 

class Array 
    def search_hash(hash) 
    key = hash.keys.first 
    value = hash.values.first 
    select { |h| h[key] == value } 
    end 
end 

z.search_hash({'a' => 3}) #=> [{"a"=>3, "b"=>4}] 

или вы можете ввести его без фигурных скобок

z.search_hash('a' => 3) 
+0

Спасибо, я реализовал его вот так, но мне было интересно, есть ли более общее решение – globetrotter

0

В основном то, что вам нужно, это что-то вроде этого:

class Array 
    def find_by_hash(h) 
    h.collect_concat do |key, value| 
     self.select{|h| h[key] == value} 
    end 
    end 
end 
+0

Я не вижу этот метод collect_concat ни в [Ruby 1.8.7] (http://ruby-doc.org/core -1.8.7/Hash.html) или в [Ruby 1.9.3] (http://www.ruby-doc.org/core-1.9.3/Hash.html) – globetrotter

+0

Ознакомьтесь с документацией для перечислимого mixin http://www.ruby-doc.org/core-1.9.3/Enumerable.html#method-i-collect_concat – Hugo

0

я не нашел подход в API, так что я думаю, что мы должны реализовать это наше.
(кстати, я думаю, что подход @megas' лучше и более удобным для чтения)

Код по TDD:

class SearchHashTest < Test::Unit::TestCase 
    def setup 
    @array_with_hash_elements = ArrayWithHashElements.new [{'a' => 1, 'b' => 2}, {'a' => 3, 'b' => 4}, {'a' => 1, 'b' => 4}] 
    end 
    def test_search_an_array_by_hash_parameter_and_return_single_hash 
    assert_equal({'a' => 3, 'b' => 4}, @array_with_hash_elements.search({'a'=>3})) 
    end 
    def test_search_an_array_by_hash_parameter_and_return_an_array 
    assert_equal([{'a' => 1, 'b' => 2}, {'a'=> 1, 'b' => 4}], @array_with_hash_elements.search({'a'=>1})) 
    end 
end 

реализован код (только для демонстрации, а не производство)

class ArrayWithHashElements 
    def initialize some_array 
    @elements = some_array 
    end 
    def search(query_hash) 
    puts "search: #{query_hash.inspect}" 
    result = [] 
    @elements.each do | array_element_in_hash_form| 
     query_hash.each_pair do | key, value | 
     if array_element_in_hash_form.has_key?(key) && array_element_in_hash_form[key] == value 
      puts "adding : #{array_element_in_hash_form.inspect} to result" 
      result << array_element_in_hash_form 
     end 
     end 
     result 
    end 
    return result.size != 1 ? result : result[0] 
    end 
end 

результат:

[email protected]:~/workspace/test$ ruby search_hash_test.rb 
Loaded suite search_hash_test 
Started 
search: {"a"=>1} 
adding : {"b"=>2, "a"=>1} to result 
adding : {"b"=>4, "a"=>1} to result 
.search: {"a"=>3} 
adding : {"b"=>4, "a"=>3} to result 
. 
Finished in 0.000513 seconds. 

2 tests, 2 assertions, 0 failures, 0 errors 
Смежные вопросы