files.json
初始文档状态:
[
{
"filename": "a",
"dir": "foo",
"type": "unknown"
},
{
"filename": "b",
"dir": "foo",
"type": "unknown"
},
{
"filename": "c",
"dir": "bar",
"type": "unknown"
},
{
"filename": "a",
"dir": "bar",
"type": "unknown"
}
]
当“ filename”值仅在文档中出现一次时,“ type”值将仅取决于“ dir”值:"dir" == "foo" --> "type" = 0
和"dir" == "bar" --> "type" = 1
当“ foo”目录和“ bar”目录中都存在“ filename”值时,“ type”必须具有== 2的值,例如:
[
{
"filename": "a",
"dir": "foo",
"type": "2"
},
{
"filename": "b",
"dir": "foo",
"type": "0"
},
{
"filename": "c",
"dir": "bar",
"type": "1"
},
{
"filename": "a",
"dir": "bar",
"type": "2"
}
]
“ dir”值将始终限于“ foo”或“ bar”值的两个可能的选择,并且永远不会为null。
甚至将设置“ filename”值,并且由于这些文件实际上是文件,因此在文档中最多只能出现两次。
我想通过从Linux中的Bash脚本运行的jq 1.5(2015年8月16日稳定版)来实现这一点。
答案 0 :(得分:3)
这里的解决方案与@CharlesDuffy的解决方案类似,但更简短,更“ jq-ish”:
(reduce .[] as $x ({}; .[$x.filename] += [$x.dir])
| map_values(unique)) as $dirs
| map( $dirs[.filename] as $d
| .type |= if $d|length > 1 then 2
elif $d[0] == "bar" then 1
else 0
end)
catalog/3
借助通用辅助函数catalog/3
:
def catalog(s; keyp; valuep):
reduce s as $x ({}; (.[$x|keyp|tostring]) += [$x|valuep]);
解决方案变得更具可读性:
(catalog(.[]; .filename; .dir) | map_values(unique)) as $dirs
| map( $dirs[.filename] as $d
| .type |= if $d|length > 1 then 2
elif $d[0] == "bar" then 1
else 0
end)
答案 1 :(得分:2)
一种方法是使用group_by
。下面,天真地使用group_by
,因此数组中最终结果的顺序由.filename;确定。如果不能令人满意,则可以使用相同的技术来构建查找表,然后将其用于原始数组。
[group_by(.filename)[]
| (map(.dir)
| unique
| if length>1 then length
elif .[0] == "foo" then 0
elif .[0] == "bar" then 1
else .[0] # just in case
end) as $type
| (.[] + {type: $type} ) ]
[
{
"filename": "a",
"dir": "foo",
"type": 2
},
{
"filename": "a",
"dir": "bar",
"type": 2
},
{
"filename": "b",
"dir": "foo",
"type": 0
},
{
"filename": "c",
"dir": "bar",
"type": 1
}
]
答案 2 :(得分:1)
jq '
([.[] | { (.filename): {(.dir): true} }] | reduce .[] as $item ({}; . * $item)) as $seen |
map(
if $seen[.filename]["foo"] and $seen[.filename]["bar"] then
.type = 2
elif $seen[.filename]["bar"] then
.type = 1
else
.type = 0
end
)
'
如果有助于理解其工作原理-$seen
的值如下所示:
{
"a": {
"foo": true,
"bar": true
},
"b": {
"foo": true
},
"c": {
"bar": true
}
}
...因此,我们可以轻松查看给定文件名的哪个目录条目。