【问题标题】:Delete json array elements based on values of subarray根据子数组的值删除json数组元素
【发布时间】:2019-09-10 03:37:22
【问题描述】:

我有以下包含此数组结构的 json 文件:

{
  "outer": [
    {
      "inner": [
        {
          "value": "val1"
        },
        {
          "value": "val3"
        }
      ]
    },
    {
      "inner": [
        {
          "value": "val2"
        },
        {
          "value": "val1"
        }
      ]
    },
    {
      "inner": [
        {
          "value": "val2"
        },
        {
          "value": "val1"
        },
        {
          "value": "val3"
        }
      ]
    }
  ]
}

我想从outer 数组中删除inner 数组,该数组的元素具有特定值并且具有特定长度。例如,如果我想删除包含值 "val1""val2"inner 数组,结果应该是:

{
  "outer": [
    {
      "inner": [
        {
          "value": "val1"
        },
        {
          "value": "val3"
        }
      ]
    },
    {
      "inner": [
        {
          "value": "val2"
        },
        {
          "value": "val1"
        },
        {
          "value": "val3"
        }
      ]
    }
  ]
}

我试过了

jq 'del( .outer[]|select(.inner[0].value == "val1"))'

但我不知道如何检查第二个条件,即长度,除此之外,这些值可能以任何顺序出现。

【问题讨论】:

  • 键总是“外”、“内”和“值”?
  • @nautical:供您考虑,在您的询问中有一个用于 JSON 操作的 alternative 解决方案 - 基于 walk-path unix 实用程序 jtc(由我开发): <file.json jtc -pw'[value]:<val1>:[-2][value]:<val2>[-2]<>f[2]<>F'。如果您希望我在单独的答案中详细说明实用程序的用法,请告诉我。
  • @Dmitry 感谢您的提议,但我无权在系统上安装新软件。我被jq困住了。

标签: json bash jq


【解决方案1】:

您正在寻找的jq 过滤器是:

del(.outer[] | select(.inner | map(.value) | sort == ["val1", "val2"]))

.inner | map(.value) 生成一个数组,其中包含与 value 键关联的值,这些值来自 .inner 包含的所有对象。

sort 是必需的,因为== 对数组进行一对一的比较。这样,无论它们的顺序如何,它都会匹配 .inner 中包含的对象。当然,您必须在右侧使用排序数组(即["val1", "val2"] 而不是["val2", "val1"])。

in action

【讨论】:

  • 感谢您的回答。虽然它在jqplay.org 上产生了所需的结果,但它在命令行上出现错误并中止:Invalid path expression with result {"inner":[{"value":"val2"}...。我的jq 版本是:jq-1.5。我是否需要更新的解决方案才能正常工作?
  • 确实,它适用于 1.6 版,但不适用于 1.5 版 :-(
  • 我升级到了 1.6 版,现在可以使用了。谢谢。
  • 显然,在 1.6 版中,del() 更加宽松,不仅接受文档中描述的路径,还接受对象。在 1.5 版中,它不接受对象。
【解决方案2】:

这是一个解决方案,至少从 1.3 版开始,应该适用于所有版本的 jq,并且可以很容易地适应其他标准,如 Q 中所述:

# A helper function for defining the retention criteria.
# It is assumed that the input is the array to be checked and that
# `match` is already sorted.
def retain( match ): (map(.value) | sort) != match;

.outer |= map( select( .inner | retain( ["val1", "val2"] ) ))

【讨论】:

    猜你喜欢
    • 2016-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-25
    • 2011-05-26
    相关资源
    最近更新 更多