Кутовий JS розрив ForEach


256

У мене є кутова петля переднього плану, і я хочу перерватися з циклу, якщо я збігаюся зі значенням. Наступний код не працює.

angular.forEach([0,1,2], function(count){
  if(count == 1){
    break;
  }
});

Як я можу це отримати?


1
Я не розумію, чому ви не просто знайдете значення замість того, щоб піти в цикл. Можливо, приклад, який ви навели, не розповідає всієї історії, але я б краще зробив те, що @Aman сказав нижче. Навіщо йти в цикл, як зазначено нижче, і запускати перевірку кожен раз, коли деякі () роблять саме це в більш елегантному стилі. Пам’ятайте, що якщо ви розглядаєте javascript як функціональну мову, не повинно бути сенсу використовувати ці для керуючих структур / while / break. Ось чому пропонують, знаходять, деякі тощо існують
Адріан Родрігес

Відповіді:


264

Немає цього зробити. Дивіться https://github.com/angular/angular.js/isissue/263 . Залежно від того, що ви робите, ви можете використовувати булеву форму, щоб просто не потрапляти в тіло петлі. Щось на зразок:

var keepGoing = true;
angular.forEach([0,1,2], function(count){
  if(keepGoing) {
    if(count == 1){
      keepGoing = false;
    }
  }
});

45
Я вважаю за краще просто додати !keepGoing && return;верхню частину функції, менше коду.
Ендрю Джослін

46
Це не найкращі практики, тут кутовий цикл для кожного не порушується, і кут неможливо зламати. Рідний для циклу приблизно на 90% швидший, ніж кутовий. Для кожного. Тож краще використовувати нативні для циклу, коли ви хочете перервати умовні збіги. Спасибі
Nishchit Dhanani

xcatly там, де я застряг ... і це допомогло ... дякую за тонну ... У будь-якому разі, я хотів би знати причину того, щоб зробити для кожного циклу нерозривний. Якщо є
Саурабх Тіварі

Це не повинно бути прийнятою відповіддю, оскільки це не порушує цикл forEach. Це дійсно спосіб не виконувати всю логіку всередині циклу.
Небулосар

296

angular.forEachЦикл не може зламатися на матчі стану.

Моя особиста порада замість цього використовувати цикл NATIVE FORangular.forEach .

Цикл NATIVE FOR на 90% швидший, ніж інший для циклів.

Для розриву циклу, для результату тестування циклу

ВИКОРИСТАННЯ ДЛЯ ШЛЯХУ В АНГУЛЬНОМУ:

var numbers = [0, 1, 2, 3, 4, 5];

for (var i = 0, len = numbers.length; i < len; i++) {
  if (numbers[i] === 1) {
    console.log('Loop is going to break.'); 
    break;
  }
  console.log('Loop will continue.');
}

1
Це не працює для мене. Все, що вона робить, це закінчити цю конкретну ітерацію петлі. Але потім переходить до наступної ітерації.
Бен

1
@Ben, Вибачте, бен, це була моя помилка, але тепер я оновлюю свою відповідь після тривалих досліджень. Я сподіваюся, що це вам допоможе. Дякую
Nishchit Dhanani

1
@LGama: - Який у вас випадок ??
Nishchit Dhanani

3
jsperf.com/angular-foreach-performance протестуйте його у власному браузері, щоб визначити, яку функцію слід вибрати. Я протестував на IE11, і це так само швидко, як на скріншоті. Тестується також Array.some (), але він повільніше, ніж Array.forEach () на IE11, але може бути швидшим, ніж angular.foreach ;-). Або протестуйте його тут jsperf.com/angular-foreach-vs-native (усі кредити йдуть оригінальному автору, а не мені ;-))
Себастьян

6
Навіть за допомогою jsperf ви не можете сказати, що "рідне для" на 90% швидше ". У вашому сценарії це дуже залежить від того, наскільки дороге виконання внутрішньої функції, і скільки виконань можна зберегти, вийшовши з циклу (перерви) завчасно.
hgoebl

22

будь ласка, використовуйте деякі або всі екземпляри ForEach,

Array.prototype.some:
some is much the same as forEach but it break when the callback returns true

Array.prototype.every:
every is almost identical to some except it's expecting false to break the loop.

Приклад для деяких:

var ary = ["JavaScript", "Java", "CoffeeScript", "TypeScript"];

ary.some(function (value, index, _ary) {
    console.log(index + ": " + value);
    return value === "JavaScript";
});

Приклад для кожного:

var ary = ["JavaScript", "Java", "CoffeeScript", "TypeScript"];

ary.every(function(value, index, _ary) {
    console.log(index + ": " + value);
    return value.indexOf("Script") > -1;
});

Знайдіть більше інформації
http://www.jsnoob.com/2013/11/26/how-to-break-the-foreach/


ні @ AngelS.Moreno, всі вважають за краще використовувати локальну змінну замість методу, розробленого спеціально для конкретного випадку
Одід Нив

18

Використовуйте метод масиву

 var exists = [0,1,2].some(function(count){
      return count == 1
 });

існує, повернеться true, і ви можете використовувати це як змінну у своїй функції

if(exists){
    console.log('this is true!')
}

Масив деякий метод - Javascript


4
Для мене єдиною причиною використання angular.forEach()є те, що я повинен підтримувати IE8, у якого немає Array.forEach()... або Array.some().
Bennett McElwee

2
Ви можете легко заповнити Array.forEach легко. Дивіться внизу сторінки: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
zumalifeguard

6

Наскільки мені відомо, Angular не забезпечує такої функції. Ви можете скористатися find()для цього функцією підкреслення (це в основному forEach, який виривається з циклу, як тільки функція поверне значення true).

http://underscorejs.org/#find


це може вирішити проблему збоку, але це не перерве цикл.
Elise Chant

Або рідний для циклу
шанті

6

Якщо ви використовуєте jQuery (отже, не jqLite) спільно з AngularJS, ви можете повторити з $ .each - що дозволяє розбивати та продовжувати на основі булевого вираження зворотного значення.

JSFiddle:

http://jsfiddle.net/JEcD2/1/

Javascript:

var array = ['foo', 'bar', 'yay'];
$.each(array, function(index, element){
    if (element === 'foo') {
        return true; // continue
    }
    console.log(this);
    if (element === 'bar') {
        return false; // break
    }
});

Примітка:

Хоча використання jQuery не є поганим, обидві функції Array.some або Array.every рекомендуються MDN, як ви можете прочитати в натурній документації forEach :

"Немає можливості зупинити або зламати цикл forEach. Рішення полягає у використанні Array.every або Array.some"

Наступні приклади надаються MDN:

Array.some:

function isBigEnough(element, index, array){
    return (element >= 10);
}
var passed = [2, 5, 8, 1, 4].some(isBigEnough);
// passed is false
passed = [12, 5, 8, 1, 4].some(isBigEnough);
// passed is true

Array.every:

function isBigEnough(element, index, array){
    return (element >= 10);
}
var passed = [12, 5, 8, 130, 44].every(isBigEnough);
// passed is false
passed = [12, 54, 18, 130, 44].every(isBigEnough);
// passed is true

6

Конкретно, ви можете вийти з forEachциклу і з будь-якого місця викинути виняток.

try {
   angular.forEach([1,2,3], function(num) {
      if (num === 2) throw Error();
   });
} catch(e) {
    // anything
}

Однак краще, якщо ви використовуєте іншу бібліотеку або реалізуєте власну функцію, findфункцію в цьому випадку, тож ваш код є найвищим рівнем.


10
Ну, ти відповів на питання! Я сподіваюся, що ніхто цього не робить :)
Джейсон Кокс

Закидання винятків - це не дуже вдалий спосіб вирішення ситуації. Швидше перевірити рішення , що надається @ dnc253 stackoverflow.com/a/13844508/698127
Aamol

4

Спробуйте це як перерву;

angular.forEach([0,1,2], function(count){
  if(count == 1){
    return true;
  }
});

3

Як свідчать інші відповіді, Angular не забезпечує цю функціональність. jQuery, однак, і якщо ви завантажили jQuery так само, як і Angular, ви можете використовувати

jQuery.each ( array, function ( index, value) {
    if(condition) return false; // this will cause a break in the iteration
})

Дивіться http://api.jquery.com/jquery.each/


2
ОП попросила рішення AngularJS, правильна відповідь - НЕ :)
Шеннон Хочкінс

3

Зазвичай немає можливості розбити цикл "кожного" в JavaScript. Що зазвичай можна зробити - це використовувати метод "короткого замикання".

    array.forEach(function(item) {
      // if the condition is not met, move on to the next round of iteration.
      if (!condition) return;

      // if the condition is met, do your logic here
      console.log('do stuff.')
    }


2

break Неможливо досягти в кутовому дляEach, нам потрібно модифікувати forEach для цього.

$scope.myuser = [{name: "Ravi"}, {name: "Bhushan"}, {name: "Thakur"}];  
                angular.forEach($scope.myuser, function(name){
                  if(name == "Bhushan") {
                    alert(name);
                    return forEach.break(); 
                    //break() is a function that returns an immutable object,e.g. an empty string
                  }
                });

Ця відповідь не здається повною. Будь ласка, вкажіть, чи break()потрібно це визначати чи тим, що це вже частина кутового. Будь ласка, визначте, якщо ні.
геодезичний

2

Ви можете скористатися цим:

var count = 0;
var arr = [0,1,2];
for(var i in arr){
   if(count == 1) break;
   //console.log(arr[i]);
}

1
var ary = ["JavaScript", "Java", "CoffeeScript", "TypeScript"];
var keepGoing = true;
ary.forEach(function(value, index, _ary) {
    console.log(index)
    keepGoing = true;
    ary.forEach(function(value, index, _ary) {
        if(keepGoing){ 
            if(index==2){
                keepGoing=false;
            }
            else{
                console.log(value)
            }

        }      
    });
});

0
$scope.arr = [0, 1, 2];  
$scope.dict = {}
for ( var i=0; i < $scope.arr.length; i++ ) {
    if ( $scope.arr[i] == 1 ) {
        $scope.exists = 'yes, 1 exists';
        break;
    }
 }
 if ( $scope.exists ) {
     angular.forEach ( $scope.arr, function ( value, index ) {
                      $scope.dict[index] = value;
     });
 }

0

Я вважаю за краще зробити це поверненням. Покладіть петельну частину в приватну функцію і поверніться, коли ви хочете зламати цикл.


0

Я розумію, що це старе, але фільтр масиву може робити все, що вам потрібно:

var arr = [0, 1, 2].filter(function (count) {
    return count < 1;
});

Потім можна запустити arr.forEachй інші функції масиву.

Я усвідомлюю, що якщо ви збираєтесь повністю скоротити операції циклу, це, ймовірно, не зробить те, що ви хочете. Для цього найкраще використовувати while.


0

Цей приклад працює. Спробуй це.

var array = [0,1,2];
for( var i = 0, ii = array.length; i < ii; i++){
  if(i === 1){
   break;
  }
}

1
Я здогадуюсь, що він не хоче forциклу, його випадки використання потрібні foreachне forпевно
Хассен Ч.


0
onSelectionChanged(event) {
    let selectdata = event['api']['immutableService']['gridOptionsWrapper']['gridOptions']['rowData'];
    let selected_flag = 0;

    selectdata.forEach(data => {
      if (data.selected == true) {
        selected_flag = 1;
      }
    });

    if (selected_flag == 1) {
      this.showForms = true;
    } else {
      this.showForms = false;
    }
}

-1

Я б використав returnзамість цього break.

angular.forEach([0,1,2], function(count){
  if(count == 1){
    return;
  }
});

Працює як шарм.


це неправильне рішення. дивіться: тест функції () {angular.forEach ([1,2,3,4,5,6,7,8,9], функція (значення, індекс) {if (значення == 2) return; console.log (значення);})} вихід:> teste (); 1 3 4 5 6 7 8 9
отавіодекампос

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.