【问题标题】:How can I use jq to invert a map and create lists for duplicate values?如何使用 jq 反转地图并为重复值创建列表?
【发布时间】:2021-05-25 22:51:27
【问题描述】:

假设我有一个这样的 JSON 映射:

{
  "a": "1",
  "b": "3",
  "c": "2",
  "d": "1"
}

如何反转它并为重复项创建列表。所以结束了:

{
 "1": [ "a", "d"],
 "2": "c",
 "3": "b" 
}

{
 "1": [ "a", "d"],
 "2": ["c"],
 "3": ["b"] 
}

谢谢!!!

【问题讨论】:

标签: json jq inverse-relationship


【解决方案1】:

由于 JSON 对象具有明显的数学函数解释,因此它具有关系逆,正如问题中提到的第二种可能性所暗示的那样,它与具有数组值键的 JSON 对象非常相似。

不幸的是,由于 JSON 对象中的键都必须是 JSON 字符串,因此 JSON 对象到 JSON 对象的任何“反向”映射都必须限制域或附带警告。

以下定义避开了对域的限制,而是需要注意它实际上返回的是 map_values(tostring) 的倒数;也就是说,实际上,它将输入 JSON 对象的所有值都视为字符串。例如,它不区分 {"k":1} 和 {"k":"1"}。

inverseMapping

下面的实现避免了group_by所需要的排序:

# Input: a JSON object, $in, viewed as a mapping of keys to strings;
# Output: a JSON object, all values of which are arrays.
# The output represents the inverse relation defined
# by $in|map_values(tostring)
def inverseMapping: 
  reduce to_entries[] as $pair ({};
    .[$pair.value|tostring] += [$pair.key]);

示例:使用问题中的 JSON 数据,输出将是:

{"1":["a","d"],"3":["b"],"2":["c"]}

quasiInverseMapping

以下函数实现了问题中提到的第一种可能性所设想的转换:

# Input: a JSON object, $in;
# Output: a JSON object, $out, representing the inverse relation
#         as above but such that:  
#         if ($in[$key]|tostring) is a distinct value, $v,
#         then $out[$v] == $key
def quasiInverseMapping:
  reduce to_entries[] as $pair ({};
    ($pair.value|tostring) as $v
     | if (.[$v]|type) == "array" then .[$v] += [$pair.key]
       elif .[$v] then .[$v] = [.[$v], $pair.key]
       else .[$v] = $pair.key
       end) ;

示例:使用问题中的 JSON 数据,输出将是:

{"1":["a","d"],"3":"b","2":"c"}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-16
    • 1970-01-01
    • 1970-01-01
    • 2021-02-09
    • 2019-10-24
    • 1970-01-01
    相关资源
    最近更新 更多