【问题标题】:Unique count of json key/values using jq使用 jq 的 json 键/值的唯一计数
【发布时间】:2021-11-10 01:36:33
【问题描述】:

我真的很难做到这一点,所以我很抱歉(jq 不是我的强项)。

我有一个像这样的 json 数组的文件:

[
  {
    "name": "aaaaa",
    "description": "aaaaa",
    "attributes": [
      {
        "trait": "Color 1",
        "value": "Blue"
      },
      {
        "trait": "Color 2",
        "value": "Yellow"
      },
      {
        "trait": "Hair",
        "value": "Wild"
      }
    ]
  },
  {
    "name": "bbbbb",
    "description": "bbbbbb",
    "attributes": [
      {
        "trait": "Color 1",
        "value": "Blue"
      },
      {
        "trait": "Color 2",
        "value": "Red"
      },
      {
        "trait": "Hair",
        "value": "Wild"
      }
    ]
  }
]

我想输出一个显示每个特征计数的 json 对象,因此最终结果将包含类似

{
   "Color 1": {
        "Blue":2
   },
   "Color 2":{
        "Yellow":1,
        "Red":1
   },
   "Hair":{
        "Wild":2
   }
}
  

这可能不太难,但就像我说的,我很讨厌 jq :)

【问题讨论】:

    标签: arrays json group-by count jq


    【解决方案1】:

    牢记group bybag-of-words 的概念,定义如下:

    def bow(stream): 
      reduce stream as $word ({}; .[($word|tostring)] += 1);
    

    不难看出,下面的结果如下所示:

    map(.attributes[])
    | group_by(.trait)
    | map( { (.[0].trait):  bow(.[].value) } )
    
    [{"Color 1":{"Blue":2}},{"Color 2":{"Yellow":1,"Red":1}},{"Hair":{"Wild":2}}]
    

    因此,要获得您想要的结果,只需将| add 添加到管道即可。

    【讨论】:

    • 天哪,这太疯狂了。我什至不知道您可以在 jq 中定义函数,这很整洁。这是一个可以帮助某人的oneliner:$ cat * | jq -s 'def bow(stream): 减少流为 $word ({}; .[($word|tostring)] += 1);地图(.attributes[]) | group_by(.trait_type)| map( { (.[0].trait_type): bow(.[].value) } ) ' 该目录包含我与 -s 一起 slurped 的单个 json 文件。非常感谢!
    • 您不会碰巧知道如何对它们进行排序吗?我尝试了 -S 以及管道排序,但它似乎不起作用,因为它是按键(属性,按字母顺序)排序,而不是值。
    • 你会使用sort_by,例如(bow(.[].value) | to_entries | sort_by(.key) | from_entries)
    【解决方案2】:
    const traits = input.reduce((aggr, obj) => aggr.concat(obj.attributes), []);
    const traitSet = traits.reduce((aggr, {trait, value}) => {
     if(!aggr[trait]) {
       aggr[trait] = {};
     }
    
     if(!aggr[trait][value]){
      aggr[trait][value] = 0;
     }
    
     aggr[trait][value] = aggr[trait][value] + 1
     return aggr;
    }, {});
    
    
    console.log(traitSet);
    // or console.log(JSON.stringify(traitSet)) - since you asked for JSON
    

    只是一个非常快速的版本和香草版本。使用 lodash 之类的库,可以使这段代码链接起来或不那么冗长。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-05
      • 1970-01-01
      • 1970-01-01
      • 2018-11-27
      • 2021-12-29
      • 2021-11-27
      相关资源
      最近更新 更多