Skip to content

Instantly share code, notes, and snippets.

@astashov
Last active December 17, 2015 21:29
Show Gist options
  • Save astashov/5675104 to your computer and use it in GitHub Desktop.
Save astashov/5675104 to your computer and use it in GitHub Desktop.
Юрина задачка. Я не делал никаких проверок правильности ввода и схемы, будем считать что они все правильные. По сути, все что делает скриптик - конвертирует массив со схемой во что-то, что знает контекст получше, ну там когда какой тип данных встречается. А потом рекурсивно проходит по input'у и применяет схему.
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"}]}
@svenyurgensson
Copy link

Ну ты много, я должен сказать, наколбасил кода.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment