jsonata:删除数组中的第一次出现项目

发布于 2025-01-20 02:17:39 字数 1527 浏览 1 评论 0原文

我想删除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;
)

do notworkbecaueabairablesareLocal不起作用,因为找到的变量是本地范围的。因此,我想我问题的第一部分是:可以使这种方法起作用吗?

它似乎没有工作的事实使我尝试了第二种方法,即通过包含arrayfoundalReady boolean和的对象进行状态。 ItemToExclude

它有效,但并不优雅。

实现这一目标的惯用方法是什么?

I want to remove the first occurrence of an element in an array in JSONata.

I tried this:

(
    $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 does not work because the found variable is locally scoped. So I guess the first part of my question is: could this kind of approach be made to work?

The fact that it didn't seem to work made me try the second approach, of carrying state through an object that contains the array, the foundAlready boolean and the itemToExclude

It works, but it isn't elegant.

What is the idiomatic JSONata way to pull this off?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

真心难拥有 2025-01-27 02:17:39

你是对的,似乎没有办法修改来自外部作用域的 $found 变量。真是太糟糕了!

您的基于归约的替代方案走在正确的轨道上。 @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 })
)

如果你想尝试一下,这里有一个 在 JSONata Playground 中链接到它

You're right that there seems to be no way to modify the $found variable that's from the outer-scope. That's a bummer!

You were on the right track with your reduce-based alternative. @aeberhart beat me to it, but I came up with a very similar solution:

(
  $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 })
)

If you want to play around with it, here's a link to it in the JSONata Playground.

信愁 2025-01-27 02:17:39

您可以使用$ drief( https://docs.jsonata.org/docs.jsonata.org/higher-order-erord-erfor--prode-----功能#降低)找到项目的第一次出现。 $减少迭代术语,并通过累加器(第一个索引)以及当前索引和值。我们可以将累加器初始化为-1,如果仍然为-1,并且该值与搜索匹配,则将索引返回为新的累加器值。

一旦有索引,我们就可以使用$ filter( https://docs.jsonata。 org/高级函数#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)
)

You can use $reduce (https://docs.jsonata.org/higher-order-functions#reduce) to find the first occurrence of an item. $reduce iterates over an array and passes an accumulator (the first index) as well as the current index and value. We can initialize the accumulator to -1 and if it is still -1 and the value matches the search, we return the index as the new accumulator value.

Once we have the index, we can use $filter (https://docs.jsonata.org/higher-order-functions#filter) to remove that index from the array:

(
    $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)
)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文