数组=>["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
,这意味着您不需要学习像jq
s 这样的新语言,并且可以重用您所知道的知识来处理其他格式,例如 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"
]