无需在 jq 中排序即可获得唯一

无需在 jq 中排序即可获得唯一

数组=>["cross", "base", "cross", "dunk"]

我想删除所有重复的值而不排序。

命令:jq '. | unique' file.json

输出:["base", "cross", "dunk"]

预期输出:["cross", "base", "dunk"]

答案1

map({key:.,value:1})|from_entries|keys_unsorted

作为替代方案unique似乎可行。

map将数组变成:

[{"key":"cross","value":1},{"key":"base","value":1},{"key":"cross","value":1},{"key":"dunk","value":1}]

from_entries将其变成:

{"cross":1,"base":1,"dunk":1}

由于对象的两个元素不能具有相同的键,因此删除此时的重复项。

并按keys_unsorted原始顺序返回该对象的键。

遵循相同原理的更短/更简单的替代方案:

map({(.):1})|add|keys_unsorted

或者您可以使用更通用的编程语言,例如perl

perl -l -0777 -MJSON::PP -MList::Util=uniq -pe '
  $_ = encode_json[uniq @{decode_json $_}]' array.json

-p是 sed 模式,将 的每条记录拉array.json$_以使e表达式起作用。

-0777将记录分隔符设置为不可能的值,这意味着只有一条记录是完整文件(另请参阅-g较新版本的 obble perl)。

decode_json $_解码该记录并返回一个数组引用,@{...}将列表传递给uniq[...]将结果传递给另一个数组引用encode_json,打印结果$_(后跟换行符-l)。

Perl 有许多 JSON 插件。 JSON::PP(纯 Perl 的 PP)是 Perl 核心的一部分,因此应该始终可用。 JSON::XS 会更高效,并且还附带一个json_xs可以在 shell 脚本中方便使用的函数:

json_xs -e 'use List::Util "uniq"; $_ = [uniq @$_]' < array.json

如果您已经熟悉perl,这意味着您不需要学习像jqs 这样的新语言,并且可以重用您所知道的知识来处理其他格式,例如 XML、YAML 等。

答案2

用于reduce()从输入构建唯一元素的结果数组:

jq 'reduce .[] as $a ([]; if IN(.[]; $a) then . else . += [$a] end)' file.json

这本质上是迭代数组 in file.json,将每个元素添加到新数组中,除非它已经存在于该数组中。

测试:

$ jq . file.json
[
  "cross",
  "base",
  "cross",
  "dunk"
]
$ jq 'reduce .[] as $a ([]; if IN(.[]; $a) then . else . += [$a] end)' file.json
[
  "cross",
  "base",
  "dunk"
]

相关内容