【问题标题】:jq: groupby and nested json arraysjq:groupby 和嵌套的 json 数组
【发布时间】:2019-05-17 03:46:13
【问题描述】:

假设我有:[[1,2], [3,9], [4,2], [], []]

我想知道要获取的脚本:

  • 非空嵌套列表的数量。即想得到:[3,2]

  • 包含或不包含数字3的嵌套列表的数量。即想获取:[1,4]

  • 元素总和不小于4 的嵌套列表的数量。即想得到:[3,2]

即嵌套数据分区的基本示例。

【问题讨论】:

  • 你有什么尝试吗?
  • 是的,我不能让它工作,否则我不会问。 :)
  • 那么你应该与我们分享你失败的尝试,给我密码这里非常不鼓励提问
  • "Give me the code" 对于像 java 和 c++ 这样成熟的语言的问题是不鼓励的。此外,这显然不是我原来的问题。这显然是一个 MCVE。我鼓励您采用“高峰”采取的方法。
  • 不,不管是什么语言,我都不会回答这样的问题

标签: json group-by jq data-partitioning


【解决方案1】:

由于 stackoverflow.com 不是编码服务,我将把这个回答限制在第一个问题上,希望它能让你相信学习 jq 是值得的。

让我们从细化关于列表计数的问题开始 “哪些是/不是空的”以强调答案中的第一个数字应对应于空列表的数量(2),第二个数字对应于其余的(3)。也就是说,要求的答案应该是[2,3]

使用内置过滤器的解决方案

下一步可能是询问是否可以使用group_by。如果顺序无关紧要,我们可以简单地写:

group_by(length==0) | map(length)

这返回[3,2],这不是我们想要的。现在值得检查有关 group_by 应该做什么的文档。在https://stedolan.github.io/jq/manual/#Builtinoperatorsandfunctions查看详细信息时, 我们看到 group_by 的设计确实按分组值排序。

由于在 jq,false < true,我们可以通过编写来修复我们的第一次尝试:

group_by(length > 0) | map(length)

这很好,但是由于group_by 在我们真正需要的只是一种计数方式的情况下做了大量工作,很明显我们应该能够提出一个更有效(并且希望不那么不透明)的解决方案。

有效的解决方案

问题的核心归结为计数,所以让我们定义一个通用的tabulate 过滤器来生成不同字符串值的计数。这是一个足以满足当前目的的定义:

# Produce a JSON object recording the counts of distinct
# values in the given stream, which is assumed to consist 
# solely of strings.
def tabulate(stream):
  reduce stream as $s ({}; .[$s] += 1);

一个有效的解决方案现在可以用两行写下来:

tabulate(.[] | length==0 | tostring )
| [.["true", "false"]]

QED

附言

上面名为tabulate 的函数有时称为bow(用于“词袋”)。在某些方面,这将是一个更好的名称,特别是因为保留名称 tabulate 以用于适用于任意流的类似功能是有意义的。

【讨论】:

  • 为什么不只是reduce .[] as $x ([]; if $x==[] then .[0]+=1 else .[1]+=1 end)?这样你就不需要排序和映射
  • 当然,但我的主要目标,正如一开始所建议的那样,不是解决特定问题。
  • 这是一个很棒的演练。非常感谢@peak
猜你喜欢
  • 2014-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多