2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Array.someとArray.everyを空の配列で実行するとどうなる?

Last updated at Posted at 2024-02-03

はじめに

Array.someArray.every、どちらも配列においてとても便利なメソッドですね。
自分も幾度となく使っていてお世話になっています。
そんな頻出のメソッドではありますが、空の配列だった時の挙動がちょっと意外だったので備忘録も兼ねてまとめてみました。

前提:Array.someArray.everyって何?

日々JavaScriptと戦っている方なら解説不要かと思いますが、一応記述しておきます。

Array.some(callbackFn)
配列の要素それぞれでcallbackFnを実行し、trueを返す要素が一つでもあればtrueを返し、そうでなければfalseを返す。
砕いて言うと、配列の中で条件を満たすものが一つでもあればOKとする ということ。
Array.every(callbackFn)
配列の要素それぞれでcallbackFnを実行し、全ての要素でtrueが返されればtrueを返し、そうでなければfalseを返す。
砕いて言うと、配列の全てで条件を満たせばOKとする ということ。
[1, 3, 10].some((x) => { return x > 5; });
// true
[1, 3, 5].some((x) => { return x > 5; });
// false

[6, 8, 10].every((x) => { return x > 5; });
// true
[6, 8, 1].every((x) => { return x > 5; });
// false

結果

というわけでタイトルのお話に戻りますが、結果は下記のようになります。

[].some((x) => { return x > 5; });
// false

[].every((x) => { return x > 5; });
// true

...あれ?
Array.someは分かります。空配列ならtrueを返す要素が一つもないので。
Array.everyはなんでそうなったんだ??おお??
君は空のカゴを指して「カゴの中に入っている物は全部りんごですか?」って聞かれたら「はい!そうです!」って言うのか???
これは納得できない。こんなこと言ったら間違いなく周りから眉をひそめられます。
もう某魔法使いの物語の最後の戦いでルーピ〇とト〇クスが死んだ時くらいに納得できない。あれはなぜ?

実際なぜこうなるのか?

そういう風に定義したからです。

 
...というのは無いと思うので、ちゃんと調べてみました。
とりあえずMDNでも見てみましょう。

every は数学における「∀ (すべての / for all)」記号と同様のふるまいをします。特に、空の配列に対しては true を返します。(空集合のすべての要素が与えられた任意の条件を満たすことは空虚に真です。)
Array.prototype.every()#解説 MDN より)

なるほど!...か?
となりましたが、「空虚な真」という言葉を調べてみると、要は命題の前件が偽なら後件の真偽に関わらず命題は真とするということだそうです。
つまり、Array.everyで空の配列を渡された時点で命題の前件は配列が空=偽になり、callbackFnによる評価は無関係に命題は空虚な真となる、つまりtrueが返されるということですね。ほ~

よし、これからは空のカゴを指して「カゴの中に入っている物は全部りんごですか?」って聞かれても「はい!そうです!」って元気に答えるぞ!

空集合について この記事を書く時にこの記事を見つけたのですが、空の配列を空集合(∅)と捉えることでtrueが返されるべき、という結論に納得することができました。
集合についてはあらゆる任意の集合は空集合を部分集合に含んでいるという基礎が記憶がわずかにある程度だったので、流石にこの部分を自分で記述するのはもっと詳しい人が既に解説してくれていることもあり気が引けました。。。
ただ、このコメントにあった X ⊂ A は成り立っても X ⊂ B は成り立たない理由は面白かったです。ありがとうございました。

そもそもの話

前半でArray.everyについて配列の全てで条件を満たせばOKとすると書きましたが、この表現自体がそもそも違っていた様子でした。
いや間違ってないのかもしれないけど、自然言語としては導かれた結果からすると明らかにおかしいですね。
書き換えるなら配列の中で条件を満たさないものが一つも無ければOKとするという表現になるでしょう。これなら空配列でtrueが返されても納得です。

...ということなんですが、そもそもMDNにはちゃんと記載されていました。

callbackFn 関数がいずれかの要素で偽値を返した場合は、すぐに false を返します。それ以外は true です。
Array.prototype.every()#返値 MDN より)

everyというメソッド名からは直感的に連想できないような表現になりますが、挙動から考えるとこれなら間違えないですね。
途中の「カゴの中に入っている物は全部りんごですか?」という質問も、Array.everyさんは実は「カゴの中に入っている物にりんご以外は含まれていないですか?」と聞かれていたということでした。
言葉で覚えるのは人間なので当然ですが、ちょっとした表現の違いで誤解が出るな~と思うと難しいですね。

余談

Array.everyと同様のメソッドは他の言語でもありますが、Pythonのall(iterable)やRustのIterator::all、JavaのarrayList.stream().allMatchも同様に空配列だと(True)trueを返すようです。
プログラミング言語の中ではこれが一般的なんですねー

最後に

ということで、メソッドの解釈や覚え方には気を付けようという教訓でした。あとは空配列のようなイレギュラーケースについては特に確認すべきということも。
また、思いっきりすっ飛ばしましたがArray.someがなぜ空配列だとfalseなのか?もちゃんと理由があるようなのですが、今回はここまでとします。
ちょっとした事象ですが、調べると奥が深くてまだまだ分からないことだらけだと痛感する出来事でした。これからも頑張って少しずつ理解していきます。

参考リンク

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?