【问题标题】:Selecting data from structured data, but the elegant functional way从结构化数据中选择数据,但优雅的功能方式
【发布时间】:2020-02-06 13:39:49
【问题描述】:

显然,随着时间的推移,我的思考能力逐渐衰退。我在从数据集中选择子数据集时遇到问题。我可以用 hacky 命令式风格解决问题,但我相信,有一个很好的函数式解决方案,可惜我找不到。

考虑一下这个数据结构(尽量不简化它超出可用性):

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}>}

但我相信会有一个使用 map、fold、zip 和 reduce 的单线。

【问题讨论】:

  • 从 Ruby 的角度来看,这是一个非常不优雅的数据结构。为什么不只是一个数组,或者一个带有数字键的哈希?像这样的类变量的真正问题是它们不是线程安全的,而且通常是一个丑陋的烂摊子。在各种不寻常的方向上发生了很多事情,这表明这可能是XY Problem。这里的最终目标是什么?
  • 注意:Ruby 是一种区分大小写的语言,大写字母在语法上具有特定的含义。变量和方法名称应该是小写字母。大写字母表示ClassNameCONSTANT_NAME 形式的常量。
  • @tadman 感谢您对数据结构的评论。我同意这个结构相当不方便。数据结构反映了家庭自动化中心的数据模型。我使用一个 API 来检索一个相当大的 XML 树,并决定创建我的模型以尽可能地等效,以免降低我的心理稳定性。 A 代表一个设备,B 一个通道,C 一个数据点的状态。每个类都有更多的属性和状态。我担心,如果我开始简化模型,我会降低改进软件功能方面的能力。
  • @tadman:请原谅,但我没有收到您的大写字母评论。 ABC 是类名,以大写字母开头(嗯...),属性以小写字母开头。浏览其他代码以获得一些灵感,我猜attribA 应该更好地命名为attrib_a
  • 不需要在问题标题的末尾加上“(Ruby)”;这就是标签的用途。

标签: ruby functional-programming


【解决方案1】:

如果您想要单线:

a.attrA.values.select { |b| b.attrB.keys == %w(b2) }

这将返回B 的实例。在您的问题中,您得到的是attrB 值,而不是B 的实例。如果这就是你想要的,那就是这个丑陋的reduce

a.attrA.values.reduce([]) { |memo, b| memo << b.attrB if b.attrB.keys == %w(b2) ; memo }

不过,我不确定你想在这里做什么?

【讨论】:

    猜你喜欢
    • 2015-12-19
    • 2011-11-30
    • 1970-01-01
    • 2018-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多