JSONata:删除数组中第一次出现的项目
JSONata: Remove first occurrence of item in array
我想删除 JSONata 中数组中第一次出现的元素。
我试过这个:
(
$largerArray := ["a","b","c","a","b","c"];
$itemToExclude := "a";
$expectedArray := ["b","c","a","b","c"];
$doesNotWorkBecauseVariablesAreLocal := function($array, $element){(
$found := false;
$filter($array, function($v){(
$isElem := $v = $element;
$shouldDrop := $isElem and $not($found);
$found := $found or $isElem;
$not($shouldDrop)
)})
)};
$doesNotWorkBecauseVariablesAreLocal($largerArray,"a");
$reduced := $reduce($largerArray, function($acc,$arrayItem){(
$array := $lookup($acc, "array");
$foundAlready := $lookup($acc,"foundAlready");
$itemToExclude := $lookup($acc,"itemToExclude");
$shouldExclude := $arrayItem = $itemToExclude and $not($foundAlready);
$foundAlready := $foundAlready or $shouldExclude;
$shouldExclude ? {"array":$array, "foundAlready":$foundAlready, "itemToExclude":$itemToExclude} : {"array":$append($array,$arrayItem), "foundAlready":$foundAlready, "itemToExclude":$itemToExclude}
)}, {"array":[], "foundAlready":false, "itemToExclude":$itemToExclude});
$reduced.array;
)
doesNotWorkBecauseVariablesAreLocal
不起作用,因为 found
变量是局部范围的。所以我想我的问题的第一部分是:这种方法是否可行?
它似乎不起作用的事实让我尝试了第二种方法,即通过包含 array
、foundAlready
布尔值和 [=15= 的对象携带状态]
可以用,但不够优雅。
实现这一目标的惯用 JSONata 方法是什么?
您可以使用 $reduce (https://docs.jsonata.org/higher-order-functions#reduce) 查找项目的第一次出现。 $reduce 迭代数组并传递累加器(第一个索引)以及当前索引和值。我们可以将累加器初始化为 -1,如果它仍然是 -1 并且值匹配搜索,我们 return 索引作为新的累加器值。
一旦我们有了索引,我们就可以使用 $filter (https://docs.jsonata.org/higher-order-functions#filter) 从数组中删除该索引:
(
$largerArray := ["a","b","c","a","b","c"];
$itemToExclude := "b";
$expectedArray := ["b","c","a","b","c"];
$dropFirst := function($array,$item){(
$index := $reduce($array, function($accumulator, $value, $index){ $value = $item and $accumulator = -1 ? $index : $accumulator }, -1 );
$filter($array, function($v, $i){$i != $index ? $v})
)};
$dropFirst($largerArray, $itemToExclude)
)
您是对的,似乎无法修改来自 outer-scope 的 $found
变量。太可惜了!
您的 reduce-based 备选方案走在正确的轨道上。 @aeberhart 打败了我,但我想出了一个非常相似的解决方案:
(
$largerArray := ["a","b","c","a","b","c"];
$findFirstOccurenceIndex := function($array, $itemToFind) {
$reduce($array, function($acc, $item, $index) {
(
$isItemToFind := $item = $itemToFind;
$acc != null ? $acc : $isItemToFind ? $index : null
)
},
null
)
};
$firstOccurence := $findFirstOccurenceIndex($largerArray, "a");
$filter($largerArray, function($item, $index) { $index != $firstOccurence })
)
如果您想尝试一下,这里有一个 link to it in the JSONata Playground。
我想删除 JSONata 中数组中第一次出现的元素。
我试过这个:
(
$largerArray := ["a","b","c","a","b","c"];
$itemToExclude := "a";
$expectedArray := ["b","c","a","b","c"];
$doesNotWorkBecauseVariablesAreLocal := function($array, $element){(
$found := false;
$filter($array, function($v){(
$isElem := $v = $element;
$shouldDrop := $isElem and $not($found);
$found := $found or $isElem;
$not($shouldDrop)
)})
)};
$doesNotWorkBecauseVariablesAreLocal($largerArray,"a");
$reduced := $reduce($largerArray, function($acc,$arrayItem){(
$array := $lookup($acc, "array");
$foundAlready := $lookup($acc,"foundAlready");
$itemToExclude := $lookup($acc,"itemToExclude");
$shouldExclude := $arrayItem = $itemToExclude and $not($foundAlready);
$foundAlready := $foundAlready or $shouldExclude;
$shouldExclude ? {"array":$array, "foundAlready":$foundAlready, "itemToExclude":$itemToExclude} : {"array":$append($array,$arrayItem), "foundAlready":$foundAlready, "itemToExclude":$itemToExclude}
)}, {"array":[], "foundAlready":false, "itemToExclude":$itemToExclude});
$reduced.array;
)
doesNotWorkBecauseVariablesAreLocal
不起作用,因为 found
变量是局部范围的。所以我想我的问题的第一部分是:这种方法是否可行?
它似乎不起作用的事实让我尝试了第二种方法,即通过包含 array
、foundAlready
布尔值和 [=15= 的对象携带状态]
可以用,但不够优雅。
实现这一目标的惯用 JSONata 方法是什么?
您可以使用 $reduce (https://docs.jsonata.org/higher-order-functions#reduce) 查找项目的第一次出现。 $reduce 迭代数组并传递累加器(第一个索引)以及当前索引和值。我们可以将累加器初始化为 -1,如果它仍然是 -1 并且值匹配搜索,我们 return 索引作为新的累加器值。
一旦我们有了索引,我们就可以使用 $filter (https://docs.jsonata.org/higher-order-functions#filter) 从数组中删除该索引:
(
$largerArray := ["a","b","c","a","b","c"];
$itemToExclude := "b";
$expectedArray := ["b","c","a","b","c"];
$dropFirst := function($array,$item){(
$index := $reduce($array, function($accumulator, $value, $index){ $value = $item and $accumulator = -1 ? $index : $accumulator }, -1 );
$filter($array, function($v, $i){$i != $index ? $v})
)};
$dropFirst($largerArray, $itemToExclude)
)
您是对的,似乎无法修改来自 outer-scope 的 $found
变量。太可惜了!
您的 reduce-based 备选方案走在正确的轨道上。 @aeberhart 打败了我,但我想出了一个非常相似的解决方案:
(
$largerArray := ["a","b","c","a","b","c"];
$findFirstOccurenceIndex := function($array, $itemToFind) {
$reduce($array, function($acc, $item, $index) {
(
$isItemToFind := $item = $itemToFind;
$acc != null ? $acc : $isItemToFind ? $index : null
)
},
null
)
};
$firstOccurence := $findFirstOccurenceIndex($largerArray, "a");
$filter($largerArray, function($item, $index) { $index != $firstOccurence })
)
如果您想尝试一下,这里有一个 link to it in the JSONata Playground。