Last active
December 17, 2015 21:29
-
-
Save astashov/5675104 to your computer and use it in GitHub Desktop.
Юрина задачка. Я не делал никаких проверок правильности ввода и схемы, будем считать что они все правильные.
По сути, все что делает скриптик - конвертирует массив со схемой во что-то, что знает контекст получше, ну там когда какой тип данных встречается. А потом рекурсивно проходит по input'у и применяет схему.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'forwardable' | |
require 'pp' | |
# * Schema may be only an array | |
# * It may not contain an array, only a symbol or a hash | |
# * The key of a hash is always a symbol and the value is always an array or array inside an array | |
# * To show that it should iterate through a collection on input, we use array in array | |
class Schema | |
include Enumerable | |
extend Forwardable | |
def_delegator :@array, :[] | |
# Need to convert all nested arrays into Schemas | |
def initialize(array) | |
@array = array.map do |item| | |
if item.is_a?(Hash) | |
item.inject({}) do |hash, (k, v)| | |
hash[k] = v[0].is_a?(Array) ? [Schema.new(v[0])] : Schema.new(v) | |
hash | |
end | |
else | |
item | |
end | |
end | |
end | |
# It yields the given block with 3 arguments - key, value and type. Like: | |
# Schema.new([ | |
# :aaa, | |
# {:ccc => [:ddd, :ggg]}, | |
# {:zzz => [[:hhh, :kkk, :mmm]]}, | |
# ]).each { |key, value, type| puts "#{key}, #{value}, #{type}" } | |
# | |
# => :aaa, nil, :all | |
# :ccc, #<Schema:0x007ff56d8cd7b8 @array=[:ddd, :ggg]>, :hash | |
# :zzz, #<Schema:0x007ff56d8cd6f0 @array=[:hhh, :kkk, :mmm]>, :collection | |
# | |
def each | |
@array.each do |item| | |
if item.is_a?(Hash) | |
type, value = if item.values[0][0].is_a?(Schema) | |
[:collection, item.values[0][0]] | |
else | |
[:hash, item.values[0]] | |
end | |
yield(item.keys[0], value, type) | |
else | |
yield(item, nil, :all) | |
end | |
end | |
end | |
end | |
def apply_schema(schema, input) | |
schema.inject({}) do |new_hash, (key, nested_schema, type)| | |
new_hash[key] = case type | |
when :all | |
input[key] | |
when :hash | |
apply_schema(nested_schema, input[key]) | |
when :collection | |
input[key].map { |nested_input| apply_schema(nested_schema, nested_input) } | |
end | |
new_hash | |
end | |
end | |
input = { | |
:aaa => "22", | |
:aaaa => "New 22", | |
:bbb => "434", | |
:ccc => { | |
:ddd => "abc", | |
:ddddd => "Not needed", | |
:ggg => "Needed", | |
:hard_to_believe => [] | |
}, | |
:zzz => [ | |
{ | |
:hhh => 126, | |
:hhhh => "Don't need", | |
:kkk => "Existing key" | |
}, | |
{ | |
:hhh => "DoobyDo", | |
:kkk => "Needed", | |
:mmm => "Existing key" | |
} | |
] | |
} | |
schema = Schema.new([ | |
:aaa, | |
:bbb, | |
:ooo, | |
{:ccc => [:ddd, :ggg]}, | |
{:zzz => [[:hhh, :kkk, :mmm]]}, | |
]) | |
pp apply_schema(schema, input) | |
# => {:aaa=>"22", | |
# :bbb=>"434", | |
# :ooo=>nil, | |
# :ccc=>{:ddd=>"abc", :ggg=>"Needed"}, | |
# :zzz=> | |
# [{:hhh=>126, :kkk=>"Existing key", :mmm=>nil}, | |
# {:hhh=>"DoobyDo", :kkk=>"Needed", :mmm=>"Existing key"}]} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Ну ты много, я должен сказать, наколбасил кода.