Видимо, моя способность мыслить функционально со временем угасла. У меня проблемы с выбором поднабора данных из набора данных. Я могу решить проблему хакерским императивным стилем, но я верю, что есть приятное функциональное решение, которое я, к сожалению, не могу найти.
Рассмотрим эту структуру данных (постарался не упростить ее за пределы юзабилити):
class C
attr_reader :attrC
def initialize(base)
@attrC = { "c1" => base+10 , "c2" => base+20, "c3" => base+30}
end
end
class B
attr_reader :attrB
@@counter = 0
def initialize
@attrB = Hash.new
@attrB["b#{@@counter}"] = C.new(@@counter)
@@counter += 1
end
end
class A
attr_reader :attrA
def initialize
@attrA = { "a1" => B.new, "a2" => B.new, "a3" => B.new}
end
end
, который создается как a = A.new
. Полный набор данных тогда будет
#<A: @attrA={"a1"=>#<B: @attrB={"b0"=>#<C: @attrC={"c1"=>10, "c2"=>20, "c3"=>30}>}>,
"a2"=>#<B: @attrB={"b1"=>#<C: @attrC={"c1"=>11, "c2"=>21, "c3"=>31}>}>,
"a3"=>#<B: @attrB={"b2"=>#<C: @attrC={"c1"=>12, "c2"=>22, "c3"=>32}>}>}>
, который подлежит выбору. Я хочу получить только те экземпляры B
, где ключ attrB
равен "b2"
.
Мой хакерский путь был бы таким:
result = Array.new
A.new.attrA.each do |_,va|
result << va.attrB.select { |kb,_| kb == "b2" }
end
p result.reject { |a| a.empty?} [0]
, что в результате дает именно то, что я предполагалось:
{"b2"=>#<C: @attrC={"c1"=>12, "c2"=>22, "c3"=>32}>}
, но я думаю, что будет одна строчка, использующая карту, фолд, молнию и уменьшение.