将键数组和值数组转换为对象
Turn array of keys and array of values into object
出于复杂的原因,涉及从 Apple plist 到 xml2json
的旅行,我有许多 JSON 文件,其中包含以下形式的数据:
{
"key": [ "key1", "key2", "key3" ],
"string": [ "value1", "value2", "value3" ]
}
我想将其转换为普通的 JSON 对象:
{
"key1": "value1",
"key2": "value2",
"key3": "value3"
}
经过一番苦思冥想,我想出了这个 jq
程序来解决这个问题:
jq '. as $d|[range(.key|length)|{"key":$d.key[.],"value":$d.string[.]}]|from_entries'
行得通,但似乎有点费解。我想知道是否有更清洁的解决方案?
这确实类似于,但不同的是,这是一个具有命名键和值元素的对象,而不是直接包含这两个数组的数组。
你提供的脚本已经很不错了!您的脚本的这种变体将索引保存到变量而不是输入对象中,这对我来说读起来更自然。然后它创建一个单键对象数组并将它们相加。
jq '[range(.key | length) as $i | {(.key[$i]): .string[$i]}] | add'
当我第一次看到这个问题时,我认为 zip
内置函数可以改善这种情况。然后我想起来了:已经有一个 zip
内置了!它只是被称为 transpose
。使用它,您可以创建如下脚本:
jq '[.key, .string] | transpose | map({key: .[0], value: .[1]}) | from_entries'
虽然也很长,但对我来说似乎也更容易理解;然而,我认为重点是可读性而不是字符数。当然,您也可以混合使用两种解决方案:
jq '[.key, .string] | transpose | map({(.[0]): .[1]}) | add'
这是一个使用 reduce 的解决方案,状态对象包含迭代索引和结果对象。它遍历 .key
在 .string
的结果中设置相应的值
.string as $v
| reduce .key[] as $k (
{idx:0, result:{}}; .result[$k] = $v[.idx] | .idx += 1
)
| .result
出于复杂的原因,涉及从 Apple plist 到 xml2json
的旅行,我有许多 JSON 文件,其中包含以下形式的数据:
{
"key": [ "key1", "key2", "key3" ],
"string": [ "value1", "value2", "value3" ]
}
我想将其转换为普通的 JSON 对象:
{
"key1": "value1",
"key2": "value2",
"key3": "value3"
}
经过一番苦思冥想,我想出了这个 jq
程序来解决这个问题:
jq '. as $d|[range(.key|length)|{"key":$d.key[.],"value":$d.string[.]}]|from_entries'
行得通,但似乎有点费解。我想知道是否有更清洁的解决方案?
这确实类似于
你提供的脚本已经很不错了!您的脚本的这种变体将索引保存到变量而不是输入对象中,这对我来说读起来更自然。然后它创建一个单键对象数组并将它们相加。
jq '[range(.key | length) as $i | {(.key[$i]): .string[$i]}] | add'
当我第一次看到这个问题时,我认为 zip
内置函数可以改善这种情况。然后我想起来了:已经有一个 zip
内置了!它只是被称为 transpose
。使用它,您可以创建如下脚本:
jq '[.key, .string] | transpose | map({key: .[0], value: .[1]}) | from_entries'
虽然也很长,但对我来说似乎也更容易理解;然而,我认为重点是可读性而不是字符数。当然,您也可以混合使用两种解决方案:
jq '[.key, .string] | transpose | map({(.[0]): .[1]}) | add'
这是一个使用 reduce 的解决方案,状态对象包含迭代索引和结果对象。它遍历 .key
在 .string
.string as $v
| reduce .key[] as $k (
{idx:0, result:{}}; .result[$k] = $v[.idx] | .idx += 1
)
| .result