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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

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

Q&A

解決済

2回答

482閲覧

forEachのループから途中でbreakするには

pyon_kiti_jp

総合スコア250

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

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

0グッド

0クリップ

投稿2022/08/01 07:30

環境

Node.js v16.14
Ubuntu20.4

実現したいこと

カレントディレクトリ内のファイルを全て取得して、ログに出力する単純な処理です。上位6件のみログに出力し、7件以降は出力しないで、forEachから抜けたいと思っています。その処理をコードの???に記述したいのですが、どのように記述するのがベストプラクティスなのか、教えていただけませんでしょうか。

node.js

1fs.readdir("./", (err, files) => { 2 files.forEach(function(file, index) { 3 console.log(file + " : " + index); 4 if (index == 5) { ???; } 5 }); 6}); 7 console.log("おわり");

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

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

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

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

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

guest

回答2

0

MDN に注意が書かれています。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach#sect2

Note: 例外を発生する以外の方法で、forEach() ループを止めることはできません。ループ中に中断する必要がある場合、forEach() メソッドは適切な方法ではありません。

早期終了を行うには下記のような手段が適しています。
...

投稿2022/08/01 07:33

int32_t

総合スコア20659

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

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

pyon_kiti_jp

2022/08/01 07:50

そうなのですね。知りませんでした。 ご回答ありがとうございます。
guest

0

ベストアンサー

7件以降は出力しないで、forEachから抜けたいと思っています。
どのように記述するのがベストプラクティスなのか

まず、forEachはToDoリストのようなものだと考えてください。
どういう意味なのかと言うと「全部やれ」ってことです。

仮にあなたが上司として、部下にこの順番で与えた仕事をしてくれと指示したとしましょう。
その部下が自分勝手な考えでToDoリストの6件目までこなして、
7件以降を捨て始めたら「おいおい」ってなりますよね?

それと同じ事を言ってるわけです。

じゃあどういうアプローチが適切なのか?
それはforEachに入る前に配列の要素を6個に加工してやることです。

候補は色々あります

  • sliceで配列の部分的な複製を作る
  • filterの第2引数のindexで振り分ける

今回の頭から6件だけ取得するやり方としてスマートなのは前者のsliceですね
下のサンプルコードでは仮に...のファイル名が取得できた想定でfilterを使って除外、
そこからsliceで先頭6件を取得するというコードにしました。

js

1fs.readdir("./", (err, files) => { 2 files 3 .filter(file => file !== "." && file !== "..") 4 .slice(0, 6) 5 .forEach((file, index) => console.log(`${file} : ${index}`)); 6}); 7console.log("おわり");

おまけ: 途中まで処理しないとbreakできるか出来ないのかわからないケースが困る

ネイティブJSで全く道具が足りてない中、頑張ってリスト操作をやろうとするのがそもそもの過ちですね。
LodashやRamda.jsみたいなライブラリの力を借りるべきです。
Lodash: partitionの前半部だけ取り出して使うとかやればbreak的な事も実現出来ます。

ネイティブJSでやるならば
共通部分までmapで加工、
findIndexで添字を引き出して
sliceで切り取るというアプローチになるでしょうか。

reduceでステートを管理するようなアプローチもあるけど微妙。

js

1fs.readdir("./", (err, files) => { 2 files 3 .reduce((obj, it) => { 4 // for文の1行目でcontinueする作戦と同じ事をやることでbreak風の処理を実現 5 if (!obj.state) return obj; 6 obj.result.push(it); 7 // ある程度の処理が終わったら改めて継続条件の設定を行う 8 if (obj.result.length >= 6) obj.state = false; 9 return obj; 10 }, {result: [], state: true}) 11 .result 12 .forEach(it => console.log(it)); 13});

そもそも速度を考慮するのであれば、
mapやforEachを使わずfor...ofを使いましょう。
ネイティブJSはPromiseの逐次処理もfor...ofがないとお話にならないので、結局for文からは逃げられません。
ライブラリもfor文使うのも嫌なら、ClojureScriptやElmみたいな別言語に移住するべきでしょう。

投稿2022/08/01 09:07

編集2022/08/01 14:34
miyabi-sun

総合スコア21158

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

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

pyon_kiti_jp

2022/08/02 00:51

とても参考になりました。 ご丁寧にありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問