"Transposing" 个对象在 jq
"Transposing" objects in jq
我不确定 "transpose" 在这里是否正确,但我希望使用 jq
转置二维对象,例如:
[
{
"name": "A",
"keys": ["k1", "k2", "k3"]
},
{
"name": "B",
"keys": ["k2", "k3", "k4"]
}
]
我想将其转换为:
{
"k1": ["A"],
"k2": ["A", "B"],
"k3": ["A", "B"],
"k4": ["A"],
}
我可以使用 .[] | {key: .keys[], name}
拆分对象以获取键和名称列表,或者我可以使用 .[] | {(.keys[]): [.name]}
获取键值对集合 {"k1": ["A"]}
和依此类推,但我不确定这两种方法的最后串联步骤。
这些方法中的任何一种都在朝着正确的方向前进吗?有没有更好的方法?
这应该有效:
map({ name, key: .keys[] })
| group_by(.key)
| map({ key: .[0].key, value: map(.name) })
| from_entries
基本方法是将每个对象转换为 name/key 对,按键重新组合它们,然后将它们映射到对象的条目。
这会产生以下输出:
{
"k1": [ "A" ],
"k2": [ "A", "B" ],
"k3": [ "A", "B" ],
"k4": [ "B" ]
}
这里有一个简单的解决方案,可能也更容易理解。它基于可以通过添加有关附加(键 -> 值)对的详细信息来扩展字典(JSON 对象)的想法:
# input: a dictionary to be extended by key -> value
# for each key in keys
def extend_dictionary(keys; value):
reduce keys[] as $key (.; .[$key] += [value]);
reduce .[] as $o ({}; extend_dictionary($o.keys; $o.name) )
$ jq -c -f transpose-object.jq input.json
{"k1":["A"],"k2":["A","B"],"k3":["A","B"],"k4":["B"]}
对于 "name" 的所有值的情况,这是一个更好的解决方案
是不同的。它更好,因为它使用了一个完全通用的
过滤器,反转映射;也就是说,invertMapping 可以是内置的或
库函数。借助此功能,解决方案
变成简单的三行。
此外,如果"name"的值不都是唯一的,那么解
下面可以很容易地通过修改输入的初始减少来调整
(即 invertMapping 调用上方的行)。
# input: a JSON object of (key, values) pairs, in which "values" is an array of strings;
# output: a JSON object representing the inverse relation
def invertMapping:
reduce to_entries[] as $pair
({}; reduce $pair.value[] as $v (.; .[$v] += [$pair.key] ));
map( { (.name) : .keys} )
| add
| invertMapping
我不确定 "transpose" 在这里是否正确,但我希望使用 jq
转置二维对象,例如:
[
{
"name": "A",
"keys": ["k1", "k2", "k3"]
},
{
"name": "B",
"keys": ["k2", "k3", "k4"]
}
]
我想将其转换为:
{
"k1": ["A"],
"k2": ["A", "B"],
"k3": ["A", "B"],
"k4": ["A"],
}
我可以使用 .[] | {key: .keys[], name}
拆分对象以获取键和名称列表,或者我可以使用 .[] | {(.keys[]): [.name]}
获取键值对集合 {"k1": ["A"]}
和依此类推,但我不确定这两种方法的最后串联步骤。
这些方法中的任何一种都在朝着正确的方向前进吗?有没有更好的方法?
这应该有效:
map({ name, key: .keys[] })
| group_by(.key)
| map({ key: .[0].key, value: map(.name) })
| from_entries
基本方法是将每个对象转换为 name/key 对,按键重新组合它们,然后将它们映射到对象的条目。
这会产生以下输出:
{
"k1": [ "A" ],
"k2": [ "A", "B" ],
"k3": [ "A", "B" ],
"k4": [ "B" ]
}
这里有一个简单的解决方案,可能也更容易理解。它基于可以通过添加有关附加(键 -> 值)对的详细信息来扩展字典(JSON 对象)的想法:
# input: a dictionary to be extended by key -> value
# for each key in keys
def extend_dictionary(keys; value):
reduce keys[] as $key (.; .[$key] += [value]);
reduce .[] as $o ({}; extend_dictionary($o.keys; $o.name) )
$ jq -c -f transpose-object.jq input.json
{"k1":["A"],"k2":["A","B"],"k3":["A","B"],"k4":["B"]}
对于 "name" 的所有值的情况,这是一个更好的解决方案 是不同的。它更好,因为它使用了一个完全通用的 过滤器,反转映射;也就是说,invertMapping 可以是内置的或 库函数。借助此功能,解决方案 变成简单的三行。
此外,如果"name"的值不都是唯一的,那么解 下面可以很容易地通过修改输入的初始减少来调整 (即 invertMapping 调用上方的行)。
# input: a JSON object of (key, values) pairs, in which "values" is an array of strings;
# output: a JSON object representing the inverse relation
def invertMapping:
reduce to_entries[] as $pair
({}; reduce $pair.value[] as $v (.; .[$v] += [$pair.key] ));
map( { (.name) : .keys} )
| add
| invertMapping