使用jq的Diff 2数据系列值

时间:2017-11-30 12:27:03

标签: json object jq difference

我不是专家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"
  }
]

任何知识可以帮助我或者至少让我朝着正确的方向前进?

1 个答案:

答案 0 :(得分:0)

首先,请在您的示例中修复JSON。

其次,放心jq非常适合这项任务,但它会 需要对jq有所了解才能设计出完整的解决方案 问题。

自问题陈述 目前有点不明确,因为SO不是 一个免费的编程服务,我将专注于此 需要的关键功能,我需要找到它 具有相同id的两个对象之间的“差异” 其他键是数字字符串。

适合测试的数据

让我们从两个对象开始:

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"
  };

减去/ 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”值,处理边缘情况等。