如何在JSONata中获取数组元素的索引
在JSONata中获取数组匹配元素的索引
确实JSONata不像JavaScript那样有现成的Array.indexOf()函数直接返回数组元素的索引,但咱们可以用它自带的数组操作函数来实现这个需求,我给你几个实用的方法:
方法1:用$reduce实现类似JS indexOf的行为(返回第一个匹配项的索引,无匹配则返回-1)
这个方法最贴近你想要的indexOf用法,遍历数组时一旦找到符合条件的元素就记录它的索引,没找到就返回-1:
假设你的数据结构是这样的:
{ "Account": { "Order": [ {"OrderID": "order101"}, {"OrderID": "order102"}, {"OrderID": "order103"}, {"OrderID": "order104"} ] } }
对应的JSONata表达式:
$reduce(Account.Order, function($acc, $v, $i) { $v.OrderID = "order103" ? $i : $acc }, -1)
解释:$reduce遍历数组,$i是当前元素的索引,当元素的OrderID匹配目标值时,就把索引赋值给累加器$acc,否则保持原来的$acc(初始值设为-1)。运行后会返回2(因为数组索引从0开始),如果没有匹配项则返回-1。
方法2:用$map生成索引+元素的数组,再筛选提取索引
如果你想更直观地看到每个元素的索引和对应值,或者需要获取所有匹配项的索引,可以用这个方法:
获取第一个匹配项的索引
$map(Account.Order, function($v, $i) { {"index": $i, "order": $v} })[order.OrderID = "order103"].index
这个表达式先把每个元素和它的索引打包成对象,再筛选出OrderID匹配的对象,最后提取index字段,结果也是2。
获取所有匹配项的索引
如果数组中有多个符合条件的元素,比如有两个OrderID="order103"的项,用下面的表达式可以返回所有匹配的索引数组:
$map(Account.Order, function($v, $i) { $v.OrderID = "order103" ? $i : null })[$$ != null]
运行后会返回所有匹配元素的索引组成的数组,比如[2, 4](假设第5个元素也匹配)。
方法3:用$count统计匹配项之前的元素数量
如果你的数组中只有一个匹配项,还可以通过统计目标元素之前不符合条件的元素数量来得到索引:
$count(Account.Order[OrderID != "order103" and $indexOf(Account.Order, $$) < $indexOf(Account.Order, Account.Order[OrderID="order103"])])
不过这个方法不如前两种灵活,尤其是当有多个匹配项时容易出错,更推荐前两种方法。
内容的提问来源于stack exchange,提问作者wnm3




