json jq -从数组中删除重复项

zaq34kh6  于 2022-12-05  发布在  其他
关注(0)|答案(2)|浏览(156)

我想删除这个json中每个数组的重复项:

{
  "abc": [
    "five"
  ],
  "pqr": [
    "one",
    "one",
    "two",
    "two",
    "three",
    "three",
    "four",
    "four"
  ],
  "xyz": [
    "one",
    "one",
    "two",
    "two",
    "four"
  ]
}

删除重复项后的输出:

{
  "abc": [
    "five"
  ],
  "pqr": [
    "one",
    "two",
    "three",
    "four"
  ],
  "xyz": [
    "one",
    "two",
    "four"
  ]
}

我尝试了Map,uniq,group_by与jq,但没有任何帮助

vlf7wbxs

vlf7wbxs1#

unique可以删除重复项,但它会自动对数组进行排序,这可能是也可能不是你想要的。
第一个
Demo
您可以根据sort重新建立数组,并将其所有unique项目的index位置重新建立为原始顺序:

jq '.[] |= [.[[index(unique[])] | sort[]]]'

Demo
或者通过编写您自己的简单重复数据删除函数来避免任何排序行为:

jq '.[] |= reduce .[] as $i ([]; . + if index($i) then [] else [$i] end)'

Demo
在我的测试中,后者表现最好,两者都产生了

{
  "abc": [
    "five"
  ],
  "pqr": [
    "one",
    "two",
    "three",
    "four"
  ],
  "xyz": [
    "one",
    "two",
    "four"
  ]
}
wfsdck30

wfsdck302#

下面是一个无需排序的替代方法,用于获取数组(或流)中的不同项,同时保留第一次出现的顺序。
它使用了一个比其他情况下稍微复杂一点的过滤器,这是为了完全的通用性:

# generate a stream of the distinct items in `stream`
# in order of first occurrence, without sorting
def uniques(stream):
  foreach stream as $s ({};
     ($s|type) as $t
     | (if $t == "string" then $s else ($s|tostring) end) as $y
     | if .[$t][$y] then .emit = false else .emit = true | (.item = $s) | (.[$t][$y] = true) end;
     if .emit then .item else empty end );

现在只需要将这个过滤器应用到JSON中。

map_values([uniques(.[])])

相关问题