使用 jq 区分 2 个数据系列值
Diff 2 data series values using jq
我不是专家 jq 用户,现在我已经尝试了很多不同的解决方案来解决我的问题。
我有一些属于特定版本的数据系列,我想计算它们之间的差异。基础数据将始终是一个包含两个元素的数组,其中包含数据系列的值。每个系列中值的数量可以变化,即 "valX" 值的数量不是恒定的。
结果应给出所有值 "ver1"-"ver2".
下面给出的结果数据是我想要最终结果的示例。如果值缺少尾随“0”,即 1.20 => 1.2 并且缺少前导零,即 0.01 => .01,那没问题。
示例JSON源数据:
[
{
"version": "ver1",
"series": [
{
"id": "name1",
"val1": "0.77",
"val2": "1.34",
"val3": "7.89",
"val4": "6.00"
},
{
"id": "name2",
"val1": "0.34",
"val2": "1.00",
"val3": "12.15"
}
]
},
{
"version": "ver2",
"series": [
{
"id": "name1",
"val1": "0.35",
"val2": "2.34",
"val3": "6.50",
"val4": "6.01"
},
{
"id": "name2",
"val1": "2.54",
"val2": "0.55",
"val3": "13.20"
}
]
}
]
我想要这样或非常相似的结果:
[
{
"id": "name1",
"val1": "-0.42",
"val2": "1.00",
"val3": "-1.39",
"val4": "0.01"
},
{
"id": "name2",
"val1": "-2.20",
"val2": "-0.45",
"val3": "1.05"
}
]
任何有知识的人可以帮助我或至少让我朝着正确的方向前进?
首先,请修正您的示例中的 JSON。
其次,请放心,jq 非常适合这项任务,但它会
需要对 jq 有所了解才能设计出完整的解决方案
到问题。
自问题陈述
目前有点不明确,因为 SO 不是
一项免费的编程服务,我将在这里重点介绍
所需的关键功能,我认为是在寻找
具有相同 id
的两个对象之间的 "difference"
并且其其他键是数字字符串。
适合测试的数据
让我们从两个对象开始:
def s1: {
"id": "name1",
"val1": "0.77",
"val2": "1.34",
"val3": "7.89",
"val4": "6.00"
};
def s2: {
"id": "name1",
"val1": "0.35",
"val2": "2.34",
"val3": "6.50",
"val4": "6.01"
};
minus/2
这里最难的部分实际上是数值舍入,由内部函数round(n)
:
处理
# $a - $b
def minus($a; $b):
def round(n):
(if . < 0 then -1 else 1 end) as $s
| $s*10*.*n
| if (floor % 10) > 4 then (.+5) else . end
| ./10 | floor/n | .*$s;
def m($k): ($a[$k]|tonumber) - ($b[$k]|tonumber) | round(100);
reduce ($a|keys_unsorted[]) as $k ({};
if $k == "id" then .id = $a["id"]
else .[$k] = m($k)
end);
minus(s2; s1)
(如果你真的想要两个数字之间的差异
要成为一个字符串,只需添加对 tostring
的调用。)
输出
{
"id": "name1",
"val1": -0.42,
"val2": 1,
"val3": -1.39,
"val4": 0.01
}
提示
下面的 minus/2
调用在给定所提供的示例数据(更正后)时产生如下所示的结果:
map(.series) | transpose | map(minus(.[1]; .[0]))
结果:
[
{
"id": "name1",
"val1": -0.42,
"val2": 1,
"val3": -1.39,
"val4": 0.01
},
{
"id": "name2",
"val1": 2.2,
"val2": -0.45,
"val3": 1.05
}
]
其余
...由您决定。这将取决于你想要多小心
匹配 "id" 值、处理边缘情况等。
我不是专家 jq 用户,现在我已经尝试了很多不同的解决方案来解决我的问题。 我有一些属于特定版本的数据系列,我想计算它们之间的差异。基础数据将始终是一个包含两个元素的数组,其中包含数据系列的值。每个系列中值的数量可以变化,即 "valX" 值的数量不是恒定的。 结果应给出所有值 "ver1"-"ver2".
下面给出的结果数据是我想要最终结果的示例。如果值缺少尾随“0”,即 1.20 => 1.2 并且缺少前导零,即 0.01 => .01,那没问题。
示例JSON源数据:
[
{
"version": "ver1",
"series": [
{
"id": "name1",
"val1": "0.77",
"val2": "1.34",
"val3": "7.89",
"val4": "6.00"
},
{
"id": "name2",
"val1": "0.34",
"val2": "1.00",
"val3": "12.15"
}
]
},
{
"version": "ver2",
"series": [
{
"id": "name1",
"val1": "0.35",
"val2": "2.34",
"val3": "6.50",
"val4": "6.01"
},
{
"id": "name2",
"val1": "2.54",
"val2": "0.55",
"val3": "13.20"
}
]
}
]
我想要这样或非常相似的结果:
[
{
"id": "name1",
"val1": "-0.42",
"val2": "1.00",
"val3": "-1.39",
"val4": "0.01"
},
{
"id": "name2",
"val1": "-2.20",
"val2": "-0.45",
"val3": "1.05"
}
]
任何有知识的人可以帮助我或至少让我朝着正确的方向前进?
首先,请修正您的示例中的 JSON。
其次,请放心,jq 非常适合这项任务,但它会 需要对 jq 有所了解才能设计出完整的解决方案 到问题。
自问题陈述
目前有点不明确,因为 SO 不是
一项免费的编程服务,我将在这里重点介绍
所需的关键功能,我认为是在寻找
具有相同 id
的两个对象之间的 "difference"
并且其其他键是数字字符串。
适合测试的数据
让我们从两个对象开始:
def s1: {
"id": "name1",
"val1": "0.77",
"val2": "1.34",
"val3": "7.89",
"val4": "6.00"
};
def s2: {
"id": "name1",
"val1": "0.35",
"val2": "2.34",
"val3": "6.50",
"val4": "6.01"
};
minus/2
这里最难的部分实际上是数值舍入,由内部函数round(n)
:
# $a - $b
def minus($a; $b):
def round(n):
(if . < 0 then -1 else 1 end) as $s
| $s*10*.*n
| if (floor % 10) > 4 then (.+5) else . end
| ./10 | floor/n | .*$s;
def m($k): ($a[$k]|tonumber) - ($b[$k]|tonumber) | round(100);
reduce ($a|keys_unsorted[]) as $k ({};
if $k == "id" then .id = $a["id"]
else .[$k] = m($k)
end);
minus(s2; s1)
(如果你真的想要两个数字之间的差异
要成为一个字符串,只需添加对 tostring
的调用。)
输出
{
"id": "name1",
"val1": -0.42,
"val2": 1,
"val3": -1.39,
"val4": 0.01
}
提示
下面的 minus/2
调用在给定所提供的示例数据(更正后)时产生如下所示的结果:
map(.series) | transpose | map(minus(.[1]; .[0]))
结果:
[
{
"id": "name1",
"val1": -0.42,
"val2": 1,
"val3": -1.39,
"val4": 0.01
},
{
"id": "name2",
"val1": 2.2,
"val2": -0.45,
"val3": 1.05
}
]
其余
...由您决定。这将取决于你想要多小心 匹配 "id" 值、处理边缘情况等。