代码之家  ›  专栏  ›  技术社区  ›  porte64

jq:在数组的各个部分上应用不同的函数/映射

  •  0
  • porte64  · 技术社区  · 2 年前

    JSON输入是一个简单的集合

    我想根据它们的名字挑选一些元素 a1,。。,an->{“a1”:v1,…“an':vn} jq-j'[.a1,.a2,…,.an]'

    然后使用不同的函数f,g。。。 从而最终得到[f(v1),…,f(vk),g(vk+1),……,g(vn)]

    使用单个函数,过滤器将是: jq-j'[.a1,.a2,…,.an]|映射(.|f)'

    但我看不出应用不同函数f、g、…的语法(如果有的话),。。。在不同的范围内

    让我展示一下我的具体案例:

    一开始,我在手机上有一个由GPS定位产生的JSON(使用termux定位)

    {
      "latitude": 66.32418638,
      "longitude": -121.77029769,
      "altitude": 465.46502685546875,
      "accuracy": 17.6742248535156,
      "vertical_accuracy": 36.48805236816406,
      "bearing": 0.0,
      "speed": 0.0,
      "elapsedMs": 55,
      "provider": "gps"
    }
    

    我想提取纬度、经度、高程和精度 并以不同的方式处理:用5位小数对前2位进行四舍五入, 和最后2个最接近的整数,并保留一个不变

    拆分时:

    jq -j '[.latitude,.longitude]|map(.*100000|round/100000)' in.json
    jq -j '[.altitude,.accuracy]|map(.|round)' in.json
    jq -j '.provider' in.json
    

    **q1.但是我们能很容易地将这些过滤器组合成一个过滤器吗?

    q2.当处理更大的数组时,是否可以在索引范围内使用不同的函数(而不必命名属性)?

    q3.或者需要构建一个具有不同情况的全局map()函数,根据范围返回f(.)、g(.)? ** 为了解决q3,我试着玩index(),但我在JQ中的水平仍然太差。。。

    • 错误的代码*
    jq -j '[.latitude,.longitude,.altitude,.accuracy]|map(if .|index<2 then .*100000|round/100000 else .|round end)'
    
    1 回复  |  直到 2 年前
        1
  •  0
  •   pmf    2 年前

    您可以在构造阵列时直接应用这些函数:

    [
      (.latitude, .longitude | .*100000 | round/100000),
      (.altitude, .accuracy | round),
      .provider
    ]
    

    Demo

    或者使用范围应用函数:

    [.latitude, .longitude, .altitude, .accuracy, .provider]
    | .[0:2] |= map(.*100000 | round/100000)
    | .[2:4] |= map(round)
    

    Demo

    您也可以将其封装在自定义过滤器中,将索引和映射函数作为参数:

    def myfun(i;j;f): .[i:j] |= map(f);
    
    [.latitude, .longitude, .altitude, .accuracy, .provider]
    | myfun(0; 2; .*100000 | round/100000)
    | myfun(2; 4; round)
    

    Demo

    给定样本输入的输出:

    [
      66.32419,
      -121.7703,
      465,
      18,
      "gps"
    ]