【问题标题】:how to flatten a tree and build a path from properties?如何展平树并从属性构建路径?
【发布时间】:2020-07-01 17:31:15
【问题描述】:

我的目标是将具有单个文件的历史信息的文件系统(如嵌套目录)扁平化为 csv 文件以供进一步处理。 Here 是我迄今为止所尝试的。

简化的输入如下所示:

{ "dirs": [
    { 
        "name": "documents",
        "files": [
            {
                "name": "foo.bar",
                "history": [
                    { "hash": "123", "timestamp": "..."},
                    { "hash": "234", "timestamp": "..."}
                ]
            }
        ],
        "subDirs": [
            { "name": "tmp", "files": [...], "subDirs": [...]
            }
        ]        
    }
]}

棘手的部分是 csv 文件应该包含完整的目录路径,而不仅仅是目录名称。所需的输出如下所示:

"documents","foo.bar","123","..."
"documents","foo.bar","234","..."
"documents","bar.baz","345","..."
"documents","bar.baz","456","..."
"documents/tmp","deleteme","567","..."
"documents/tmp","deleteme","678","..."

使用recurse 扁平化大部分数据可以使用此查询:

.dirs[] | recurse(.subDirs[]?) | . as $d | $d.files[]? as $f | $f.history[]? as $h | [$d.name, $f.name, $h.hash, $h.timestamp] | @csv

...但我无法理解如何保留构建目录路径。任何建议将不胜感激。

【问题讨论】:

    标签: json recursion tree jq


    【解决方案1】:

    我认为您需要为此定义一个自定义递归函数,如下所示;它假定所有文件都有一个非空的history

    def f(pfix):
        ( [ pfix, .name ] | join("/") ) as $path |
        ( .files[] | .history[] as $hist | [ $path, .name, $hist[] ] ),
        ( .subDirs[] | f($path) );
    .dirs[] | f(empty) | @csv
    

    【讨论】:

    • 这非常有效。非常感谢!我有点用“递归”走到了死胡同
    • @oguzismail - 使用 jqplay 的示例数据,您的解决方案会产生错误,可以通过编写 .history[]? 来解决
    【解决方案2】:

    这是一种既不显式使用递归 (*) 也不依赖递归结构的方法:

    def names($path):
      reduce getpath($path[0:range(0; $path|length)]) as $v ("";
        if $v | type == "object" and has("name") then . + "/" + $v["name"] else . end) ;
    
    paths as $p
    | getpath($p) as $v
    | select($v | objects | has("history"))
    | [names($p), getpath($p + ["name"])]
      + ($v["history"][] | [.hash, .timestamp] )
    | @csv
    

    这会产生“绝对”路径(例如“/documents”);省略前导的“/”可以很容易地完成。


    (*) paths 是递归定义的,但以利用 jq 的尾调用优化 (TCO) 的方式定义,该优化仅适用于 arity-0 递归函数。

    【讨论】:

    • 感谢您对此的看法。它更容易掌握,但我已经使用 oguz 的答案解决了我的问题。我还在学习 jq,所以看看不同的解决方案肯定会有所帮助。
    • @Buxel 考虑到递归的缺点,这可能 - 没有测试,但仍然 - 不仅是一种不同的解决方案,而且在性能方面也是一个更好的解决方案
    • @oguzismail - 对于此类问题,未优化的递归很好。只有当递归深度很大时,它才开始变得重要。
    • 所以基本上paths 使用TCO 自动优化否则未优化的(手动)递归?我会读一些关于 TCO 的资料,谢谢!
    猜你喜欢
    • 2020-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多