0

我想比较两个 json 文件,看看是否可以从另一个中提取一个。

P1 (p1.json)

{
  "id": 12,
  "keys": ["key1","key2"],
  "body": {
    "height": "180cm",
    "wight": "70kg"
  },
  "name": "Alex"
}

P2 (p2.json)

{
  "id": 12,
  "keys": ["key2","key1"],
  "body": {
    "height": "180cm"
  }
}

可以看出,P2不完全等于P1,但可以从P1中提取(它提供的同一个人的数据较少,但数据是正确的)。

预期行为:

p1 extends p2 --> true
p2 extends p1 --> false


注意
- 无法从具有一些附加元素的同一数组中提取数组

4

2 回答 2

2

下面的定义extends/1使用纯粹基于对象的扩展定义(特别是,它不对数组进行排序)。我不清楚关于数组的 OP 要求,但下一节提供了变体定义。

# Usage: $in | extends($b) iff $in contains $b in an object-based sense
def extends($b):
  # Handle the case that both are objects:
  def objextends($x):
    . as $in | all($x|keys[]; . as $k | $in[$k] | extends($x[$k]));
  # Handle the case that both are arrays:
  def arrayextends($x):
    . as $in
    | length == ($x|length) and
        all( range(0;length); . as $i | $in[$i] | extends($x[$i]));

  if . == $b then true
  else . as $in
  | type as $intype
  | ($intype == ($b|type)) and
      (($intype == "object" and objextends($b)) or
       ($intype == "array" and arrayextends($b)))

结尾;

例子:

{a:{a:1,b:2}, b:2} | extends({a:{a:1}}) # true

{a:{a:1,b:2}, b:2} | extends({a:{a:2}}) # false

{a:{a:1,b:2}, b:[{x:1,y:2}]} | extends({a:{a:2}, b:[{x:1}]}) # true

替代定义

以下定义对数组进行排序,并且足以处理给定的示例:

# Usage: $in | extends2($b) iff $in contains $b in a way which ignores the order of array elements
def extends2($b):
  # Both are objects
  def objextends($x):
    . as $in | all($x|keys[]; . as $k | $in[$k] | extends($x[$k]));

  def arrayextends($x): ($x|sort) - sort == [];

  if . == $b then true
  else . as $in
  | type as $intype
  | ($intype == ($b|type)) and
      (($intype == "object" and objextends($b)) or
       ($intype == "array"  and arrayextends($b)))
  end;

如图所示,使用 $P1 和 $P2:

  $P1 | extends2($P2) # yields true
于 2017-10-17T12:03:48.803 回答
0

如果您知道任何子数组中没有重复项,那么您可以使用这种方法计算[path,value]tostream返回的对组之间的差异,将数组索引替换为null

def details:[
     tostream
   | select(length==2) as [$p,$v]
   | [$p|map(if type=="number" then null else . end),$v]
];

def extends(a;b): (b|details) - (a|details) == [];

ifP1P2are 函数返回样本数据

def P1: {
    "id": 12,
    "keys": ["key1","key2"],
    "body": {
      "height": "180cm",
      "wight": "70kg"
    },
    "name": "Alex"
  }
;

def P2: {
    "id": 12,
    "keys": ["key2","key1"],
    "body": {
      "height": "180cm"
    }
  }
;

然后

  extends(P1;P2)  # returns true
, extends(P2;P1)  # returns false

在存在重复的情况下,结果不太清楚。例如

  extends(["a","b","b"];["a","a","b"])  # returns true

在线尝试!

于 2017-10-17T18:50:43.990 回答