我有一个这样的json:
[ {"data":"a"}, {"data":"b"}, {"data":"c"} ]
使用jq我想添加一个递增的id字段,如下所示:
[ {"data":"a","id":"xx_1"}, {"data":"b","id":"xx_2"}, {"data":"c","id":"xx_3"} ]
我似乎找不到正确的jq命令,有人知道吗?
eeq64g8w1#
下面定义的enumerate/1是一个有用的通用库函数,可用于解决此类问题,它是面向流的,这也使得它值得了解。为了与jq的“索引原点”一致,它从0开始计数,因此first + 1满足这个特定问题的要求:
enumerate/1
first + 1
def enumerate(s): foreach s as $x (-1; .+1; [., $x]); [enumerate(.[]) | last + {id: "xx_\(first + 1)"}]
wooyq4lh2#
这里有一个方法:
to_entries | map( (.value.id = "xx_\(1+.key)" ) | .value)
下面是另一种方法,但需要jq 1.5:
def add_id(prefix): [ foreach .[] as $o (0; . + 1; $o + {"id": (prefix + tostring) }) ]; add_id("xx_")
示例:
$ jq -c -f add_id.jq [ {"data":"a"}, {"data":"b"}, {"data":"c"} ]
输出:
[{"data":"a","id":"xx_1"},{"data":"b","id":"xx_2"},{"data":"c","id":"xx_3"}]
第三种方法是使用transpose:
transpose
def add_id(prefix): [ ., [ range(0;length) | {"id": (prefix + tostring) } ] ] | transpose | map(add);
(If你的jq没有transpose/0,它的jq定义可以很容易地找到,例如通过谷歌搜索。
hkmswyz63#
这里有两个解决方案。一个使用foreach,它在foreach状态下保存一个计数器,同时迭代输入数组,将值收集回结果数组。这类似于peak的add_id函数。
[ foreach .[] as $e ( 0 ; .+1 ; $e + {"id":"xx_\(.)"} ) ]
另一个使用reduce,它在迭代数组索引时将输入数组保持在reduce状态,更新每个元素。
reduce range(0,length) as $i ( . ; .[$i].id = "xx_\($i+1)" )
我认为reduce是这种情况下最简单的方法。
q8l4jmvw4#
var data=[ {"data":"a"}, {"data":"b"}, {"data":"c"} ]; var cnt=0; data.map(function(data){ data.id="xx_"+cnt; cnt++; }) console.log(data);
4条答案
按热度按时间eeq64g8w1#
下面定义的
enumerate/1
是一个有用的通用库函数,可用于解决此类问题,它是面向流的,这也使得它值得了解。为了与jq的“索引原点”一致,它从0开始计数,因此
first + 1
满足这个特定问题的要求:wooyq4lh2#
这里有一个方法:
下面是另一种方法,但需要jq 1.5:
示例:
输出:
第三种方法是使用
transpose
:(If你的jq没有transpose/0,它的jq定义可以很容易地找到,例如通过谷歌搜索。
hkmswyz63#
这里有两个解决方案。一个使用foreach,它在foreach状态下保存一个计数器,同时迭代输入数组,将值收集回结果数组。这类似于peak的add_id函数。
另一个使用reduce,它在迭代数组索引时将输入数组保持在reduce状态,更新每个元素。
我认为reduce是这种情况下最简单的方法。
q8l4jmvw4#