JavaScriptのネストされたループから抜け出す最良の方法は何ですか?
-
06-07-2019 - |
質問
Javascriptのネストされたループから抜け出す最良の方法は何ですか?
//Write the links to the page.
for (var x = 0; x < Args.length; x++)
{
for (var Heading in Navigation.Headings)
{
for (var Item in Navigation.Headings[Heading])
{
if (Args[x] == Navigation.Headings[Heading][Item].Name)
{
document.write("<a href=\""
+ Navigation.Headings[Heading][Item].URL + "\">"
+ Navigation.Headings[Heading][Item].Name + "</a> : ");
break; // <---HERE, I need to break out of two loops.
}
}
}
}
解決
Perlのように、
loop1:
for (var i in set1) {
loop2:
for (var j in set2) {
loop3:
for (var k in set3) {
break loop2; // breaks out of loop3 and loop2
}
}
}
EMCA-262セクション12.12で定義されています。 [MDN Docs]
Cとは異なり、これらのラベルは continue
および break
、Javascriptには goto
がないため。
他のヒント
それを関数でラップしてから、単に return
します。
パーティーには少し遅れていますが、以下はGOTO /ラベルや関数のラッピングを使用しない言語に依存しないアプローチです:
for (var x = Set1.length; x > 0; x--)
{
for (var y = Set2.length; y > 0; y--)
{
for (var z = Set3.length; z > 0; z--)
{
z = y = -1; // terminates second loop
// z = y = x = -1; // terminate first loop
}
}
}
逆さまに自然に流れるので、GOTO以外の人が喜ぶはずです。欠点として、内部ループは終了する前に現在の反復を完了する必要があるため、一部のシナリオでは適用できない場合があります。
これは非常に古いトピックであることに気づきましたが、私の標準的なアプローチはまだここにないので、将来のグーグル向けに投稿すると思いました。
var a, b, abort = false;
for (a = 0; a < 10 && !abort; a++) {
for (b = 0; b < 10 && !abort; b++) {
if (condition) {
doSomeThing();
abort = true;
}
}
}
var str = "";
for (var x = 0; x < 3; x++) {
(function() { // here's an anonymous function
for (var y = 0; y < 3; y++) {
for (var z = 0; z < 3; z++) {
// you have access to 'x' because of closures
str += "x=" + x + " y=" + y + " z=" + z + "<br />";
if (x == z && z == 2) {
return;
}
}
}
})(); // here, you execute your anonymous function
}
どうですか? :)
非常にシンプル
var a=[1,2,3];
var b=[4,5,6];
var breakCheck1=false;
for (var i in a){
for (var j in b){
breakCheck1=true;
break;
}
if (breakCheck1) {break;}
}
ブレーク、アボートフラグ、および追加の条件チェックを使用しないでください。このバージョンでは、条件が満たされたときにループ変数を爆発させ( Number.MAX_VALUE
にします)、すべてのループを強制的に終了させます。
// No breaks needed
for (var i = 0; i < 10; i++) {
for (var j = 0; j < 10; j++) {
if (condition) {
console.log("condition met");
i = j = Number.MAX_VALUE; // Blast the loop variables
}
}
}
デクリメント型のネストされたループには同様の答えがありましたが、これは単純なループの各ループの終了値を考慮する必要なく、インクリメント型のネストされたループに対して機能します。
別の例:
// No breaks needed
for (var i = 0; i < 89; i++) {
for (var j = 0; j < 1002; j++) {
for (var k = 0; k < 16; k++) {
for (var l = 0; l < 2382; l++) {
if (condition) {
console.log("condition met");
i = j = k = l = Number.MAX_VALUE; // Blast the loop variables
}
}
}
}
}
JavaScriptでネストされたループから抜け出す5つの方法を次に示します。
1)親ループを最後に設定します
for (i = 0; i < 5; i++)
{
for (j = 0; j < 5; j++)
{
if (j === 2)
{
i = 5;
break;
}
}
}
2)ラベルを使用
exit_loops:
for (i = 0; i < 5; i++)
{
for (j = 0; j < 5; j++)
{
if (j === 2)
break exit_loops;
}
}
3)変数を使用
var exit_loops = false;
for (i = 0; i < 5; i++)
{
for (j = 0; j < 5; j++)
{
if (j === 2)
{
exit_loops = true;
break;
}
}
if (exit_loops)
break;
}
4)自己実行機能を使用
(function()
{
for (i = 0; i < 5; i++)
{
for (j = 0; j < 5; j++)
{
if (j === 2)
return;
}
}
})();
5)通常の機能を使用
function nested_loops()
{
for (i = 0; i < 5; i++)
{
for (j = 0; j < 5; j++)
{
if (j === 2)
return;
}
}
}
nested_loops();
ループを終了制限までプッシュする方法
for(var a=0; a<data_a.length; a++){
for(var b=0; b<data_b.length; b++){
for(var c=0; c<data_c.length; c++){
for(var d=0; d<data_d.length; d++){
a = data_a.length;
b = data_b.length;
c = data_b.length;
d = data_d.length;
}
}
}
}
Coffeescriptを使用する場合、便利な「do」があります。無名関数の定義と即時実行を容易にするキーワード:
do ->
for a in first_loop
for b in second_loop
if condition(...)
return
...したがって、単に「戻る」を使用できます。ループから抜け出すため。
機能プログラミングのアプローチを示すと思いました。私のソリューションのように、ネストされたArray.prototype.some()および/またはArray.prototype.every()関数から抜け出すことができます。このアプローチの追加の利点は、 Object.keys()
がオブジェクト自身の列挙可能なプロパティのみを列挙するのに対し、&quot; for-inループは、プロトタイプチェーンのプロパティも列挙します&quot; 。
OPのソリューションに近い:
Args.forEach(function (arg) {
// This guard is not necessary,
// since writing an empty string to document would not change it.
if (!getAnchorTag(arg))
return;
document.write(getAnchorTag(arg));
});
function getAnchorTag (name) {
var res = '';
Object.keys(Navigation.Headings).some(function (Heading) {
return Object.keys(Navigation.Headings[Heading]).some(function (Item) {
if (name == Navigation.Headings[Heading][Item].Name) {
res = ("<a href=\""
+ Navigation.Headings[Heading][Item].URL + "\">"
+ Navigation.Headings[Heading][Item].Name + "</a> : ");
return true;
}
});
});
return res;
}
見出し/アイテムの繰り返しを減らすソリューション:
var remainingArgs = Args.slice(0);
Object.keys(Navigation.Headings).some(function (Heading) {
return Object.keys(Navigation.Headings[Heading]).some(function (Item) {
var i = remainingArgs.indexOf(Navigation.Headings[Heading][Item].Name);
if (i === -1)
return;
document.write("<a href=\""
+ Navigation.Headings[Heading][Item].URL + "\">"
+ Navigation.Headings[Heading][Item].Name + "</a> : ");
remainingArgs.splice(i, 1);
if (remainingArgs.length === 0)
return true;
}
});
});
すでに swilliams によって言及されていますが、下の例(Javascript)で:
// Function wrapping inner for loop
function CriteriaMatch(record, criteria) {
for (var k in criteria) {
if (!(k in record))
return false;
if (record[k] != criteria[k])
return false;
}
return true;
}
// Outer for loop implementing continue if inner for loop returns false
var result = [];
for (var i = 0; i < _table.length; i++) {
var r = _table[i];
if (!CriteriaMatch(r[i], criteria))
continue;
result.add(r);
}
うーん、10歳のパーティーにこんにちは?
なぜforに何らかの条件を入れないのですか?
var condition = true
for (var i = 0 ; i < Args.length && condition ; i++) {
for (var j = 0 ; j < Args[i].length && condition ; j++) {
if (Args[i].obj[j] == "[condition]") {
condition = false
}
}
}
このように、必要なときに停止します
私の場合、Typescriptを使用して、配列を通過して条件が満たされたときに停止するsome()を使用できます だから私のコードは次のようになります:
Args.some((listObj) => {
return listObj.some((obj) => {
return !(obj == "[condition]")
})
})
これと同様に、条件が満たされた直後にループが停止しました
リマインダー:このコードはTypeScriptで実行されます
XXX.Validation = function() {
var ok = false;
loop:
do {
for (...) {
while (...) {
if (...) {
break loop; // Exist the outermost do-while loop
}
if (...) {
continue; // skips current iteration in the while loop
}
}
}
if (...) {
break loop;
}
if (...) {
break loop;
}
if (...) {
break loop;
}
if (...) {
break loop;
}
ok = true;
break;
} while(true);
CleanupAndCallbackBeforeReturning(ok);
return ok;
};
最良の方法は-
1)最初と2番目のループで使用される両方の配列をソートします。
2)アイテムが一致した場合、内部ループを中断し、インデックス値を保持します。
3)次の反復を開始するとき、ホールドインデックス値で内部ループを開始します。