質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
コールバック

コールバックは他のコードに引数として渡されるコードのことを指します。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

3回答

1407閲覧

配列の走査を途中で打ち切って、コールバックの返り値を返したい

maisumakun

総合スコア145183

コールバック

コールバックは他のコードに引数として渡されるコードのことを指します。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

1クリップ

投稿2021/12/15 06:32

前提条件

JavaScriptのArrayには、イテレーション系のメソッドがいくつかありますが、その中でも途中で打ち切れるものとして以下のようなものがあります。

  • .some, .every…真偽値を返す
  • .find…配列の値1つを返す
  • .findIndex…要素の位置を返す

疑問内容

ここで、コールバックの値を返すような手法は存在しないのでしょうか。一例としては、「正規表現の入った配列を前から順にチェックしていって、いちばん先にマッチしたもののマッチ結果を返す」というような利用例が考えられます。

代替手段

もちろん、「ふつうにforループで書く」あるいは「返り値は適当な変数に入れて、.someを使って途中打ち切りを再現する」ような方法で同じことは実行できますが、再代入や破壊的変更をしない形で書けないかな、と考えています。

.findしてからコールバックを呼ぶ」だと対象のだけコールバックが2回呼ばれてしまいますし、「.mapしてから.find」では途中打ち切りが行われません。

(なお、「例外を使って強引に値を持ち出す」という手段は、JavaScriptだと例外種別による区分が面倒だという事情もあるので、考えていません)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

js

1let cnt = 0; 2 3function test (str) { 4 return function (reg) { 5 cnt++; 6 let match = str.match (reg); 7 if (match) 8 Object.assign (this, { reg, match }); 9 return !! match; 10 }; 11} 12 13//___________ 14 15let 16 reg = [/a/, /b/, /c/, /d/], 17 rst = { }; 18 19reg.some (test ('__c___'), rst); 20console.log (rst, cnt); 21

投稿2021/12/15 07:22

babu_babu_baboo

総合スコア616

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

配列に

javascript

1Array.prototype.findTruthyReturn = function(fn) { 2 for (let i = 0; i < this.length; i ++) { 3 const rtn = fn(this[i]); 4 if (rtn) 5 return rtn; 6 } 7}

というようなメソッドを追加するのはどうでしょうか? (メソッド名が妥当かは分かりませんが。)

以下使用例です。

javascript

1const regExps = [/A(x+)B(z+)/, /A(x+)(B)/, /A(x+)B(y+)/]; 2 3const match = regExps.findTruthyReturn(r => 'AxxByy'.match(r)); 4 5if (match) { 6 console.log(match[0], match[1], match[2]); 7}

出力結果:

AxxB xx B

投稿2021/12/15 10:31

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

こういうことでしょうか?

js

1 2const arr = [ 3 /abcde/, 4 /abc/, 5 /ab/, 6]; 7const str = "abc" 8 9arr.flatMap(function (x) { 10 if (this[0] && x.test(str)) { 11 this[0] = false; 12 return x; 13 } 14 return []; 15}, [true]) 16 17// [/abc/] 18

コメントを受けて追記

js

1const arr = [ 2 /abcde/, 3 /abc/, 4 /ab/, 5]; 6const str = "abc"; 7 8[...(function* (arr, str) { 9 for (x of arr) { 10 if (x.test(str)) { 11 yield x; 12 return; 13 } 14 } 15})(arr, str)] 16 17// [/abc/]

よく考えたらジェネレータ内でforループ使っても質問の条件を満たさないのでは、と思ったので追記

ジェネレータ移譲再帰で。

js

1 2const arr = [ 3 /abcde/, 4 /abc/, 5 /ab/, 6]; 7const str = "abc"; 8 9[...(function* g(arr, str) { 10 const x = arr.next().value 11 if (x.test(str)) { 12 yield x; 13 return; 14 } 15 yield* g(arr, str); 16})(arr.values(), str)] 17 18 // [/abc/]

投稿2021/12/15 07:25

編集2021/12/16 01:16
Lhankor_Mhy

総合スコア36074

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2021/12/15 08:28 編集

それに近いことも考えたのですが、何もしないとはいえ元の配列の個数分、flatMapによるループがまわり続けてしまいます。
Lhankor_Mhy

2021/12/15 08:44

なるほど。 別回答を追記しました。
maisumakun

2021/12/18 23:07

イテレーターの拡張など、増えていくとさらに便利になりそうですね。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問