查找两个数组之间的共同项和独特项
Find common and unique items between two arrays
我使用 ec2.py 动态清单脚本和 ansible 来提取 ec2 主机及其标签名称的列表。它 returns 我 JSON 列表如下,
"tag_aws_autoscaling_groupName_asg_test": [
"aa.b.bb.55",
"1b.b.c.d"
],
"tag_aws_autoscaling_groupName_asg_unknown": [
"aa.b.bb.55",
"1b.b.c.e"
],
我正在使用 jq 来解析这个输出。
- 如何只提取这两个 ASG 共有的字段?
- 如何只提取这两个 ASG 独有的字段?
要查找两个数组之间的共同项,只需在两者之间执行集合交集即可。没有可用的交集函数,但它应该足够简单,可以自己定义。取出每个数组的唯一项,按值将它们分组,然后取出一组中超过 1 个的项。
def intersect($a; $b): [($a | unique)[], ($b | unique)[]]
| [group_by(.)[] | select(length > 1)[0]];
使用它来查找公共元素(假设您的输入实际上是一个有效的 json 对象):
$ jq 'def intersect($a; $b): [($a | unique)[], ($b | unique)[]]
| [group_by(.)[] | select(length > 1)[0]];
intersect(.tag_aws_autoscaling_groupName_asg_test;
.tag_aws_autoscaling_groupName_asg_unknown)' < input.json
[
"aa.b.bb.55"
]
要查找数组特有的项,只需执行集差。
$ jq 'def difference($a; $b): ($a | unique) - ($b | unique);
difference(.tag_aws_autoscaling_groupName_asg_test;
.tag_aws_autoscaling_groupName_asg_unknown)' < input.json
[
"1b.b.c.d"
]
difference/2
由于 jq 的“-”运算符在数组上定义的方式,unique
的一次调用足以生成 "uniquified" 答案:
def difference($a; $b): ($a | unique) - $b;
同样,对于对称差分,单次排序操作足以产生"uniquified"值:
def sdiff($a; $b): (($a-$b) + ($b-$a)) | unique;
intersect/2
这是一个更快的 intersect/2
版本,应该适用于所有版本的 jq -- 它消除了 group_by
以支持 sort
:
def intersect(x;y):
( (x|unique) + (y|unique) | sort) as $sorted
| reduce range(1; $sorted|length) as $i
([];
if $sorted[$i] == $sorted[$i-1] then . + [$sorted[$i]] else . end) ;
intersection/2
如果你有 jq 1.5,那么这里有一个类似但仍然明显更快的集合交集函数:它在两个数组的集合交集中生成元素流:
def intersection(x;y):
(x|unique) as $x | (y|unique) as $y
| ($x|length) as $m
| ($y|length) as $n
| if $m == 0 or $n == 0 then empty
else { i:-1, j:-1, ans:false }
| while( .i < $m and .j < $n;
$x[.i+1] as $nextx
| if $nextx == $y[.j+1] then {i:(.i+1), j:(.j+1), ans: true, value: $nextx}
elif $nextx < $y[.j+1] then .i += 1 | .ans = false
else .j += 1 | .ans = false
end )
end
| if .ans then .value else empty end ;
我使用 ec2.py 动态清单脚本和 ansible 来提取 ec2 主机及其标签名称的列表。它 returns 我 JSON 列表如下,
"tag_aws_autoscaling_groupName_asg_test": [
"aa.b.bb.55",
"1b.b.c.d"
],
"tag_aws_autoscaling_groupName_asg_unknown": [
"aa.b.bb.55",
"1b.b.c.e"
],
我正在使用 jq 来解析这个输出。
- 如何只提取这两个 ASG 共有的字段?
- 如何只提取这两个 ASG 独有的字段?
要查找两个数组之间的共同项,只需在两者之间执行集合交集即可。没有可用的交集函数,但它应该足够简单,可以自己定义。取出每个数组的唯一项,按值将它们分组,然后取出一组中超过 1 个的项。
def intersect($a; $b): [($a | unique)[], ($b | unique)[]]
| [group_by(.)[] | select(length > 1)[0]];
使用它来查找公共元素(假设您的输入实际上是一个有效的 json 对象):
$ jq 'def intersect($a; $b): [($a | unique)[], ($b | unique)[]]
| [group_by(.)[] | select(length > 1)[0]];
intersect(.tag_aws_autoscaling_groupName_asg_test;
.tag_aws_autoscaling_groupName_asg_unknown)' < input.json
[
"aa.b.bb.55"
]
要查找数组特有的项,只需执行集差。
$ jq 'def difference($a; $b): ($a | unique) - ($b | unique);
difference(.tag_aws_autoscaling_groupName_asg_test;
.tag_aws_autoscaling_groupName_asg_unknown)' < input.json
[
"1b.b.c.d"
]
difference/2
由于 jq 的“-”运算符在数组上定义的方式,unique
的一次调用足以生成 "uniquified" 答案:
def difference($a; $b): ($a | unique) - $b;
同样,对于对称差分,单次排序操作足以产生"uniquified"值:
def sdiff($a; $b): (($a-$b) + ($b-$a)) | unique;
intersect/2
这是一个更快的 intersect/2
版本,应该适用于所有版本的 jq -- 它消除了 group_by
以支持 sort
:
def intersect(x;y):
( (x|unique) + (y|unique) | sort) as $sorted
| reduce range(1; $sorted|length) as $i
([];
if $sorted[$i] == $sorted[$i-1] then . + [$sorted[$i]] else . end) ;
intersection/2
如果你有 jq 1.5,那么这里有一个类似但仍然明显更快的集合交集函数:它在两个数组的集合交集中生成元素流:
def intersection(x;y):
(x|unique) as $x | (y|unique) as $y
| ($x|length) as $m
| ($y|length) as $n
| if $m == 0 or $n == 0 then empty
else { i:-1, j:-1, ans:false }
| while( .i < $m and .j < $n;
$x[.i+1] as $nextx
| if $nextx == $y[.j+1] then {i:(.i+1), j:(.j+1), ans: true, value: $nextx}
elif $nextx < $y[.j+1] then .i += 1 | .ans = false
else .j += 1 | .ans = false
end )
end
| if .ans then .value else empty end ;