2013-06-02 6 views
10
$scope.clearCompleted = function() 
     { 
      angular.forEach($scope.todos, function(todo, i) 
      { 
       if(todo.done) 
       { 
        $scope.todos.splice(i, 1); 
       } 
      }); 

      if($scope.todos.length == 0) 
      { 
       $scope.isEmpty = true; 
      } 
     } 

をデクリメントこれは、配列から「行って」ドスを削除するために私のコードです が、お互いの後に2ドスが削除された場合、それだけで第二を削除します。 スプライス関数がリセットされ、スプライスされた配列が返されるからだと思います。JavaScriptのスプライス機能はインデックス

+0

はい、 '.splice()は '配列を変異させます。前方反復を使用する場合は、これを考慮する必要があります。 –

答えて

18

あなたは反復処理した配列から要素をスプライスします。したがって、 "todos"のインデックスは縮小されます。私の悪い英語のために申し訳ありません。

var notDonedTodos = []; 
angular.forEach($scope.todos, function(todo, i) 
{ 
    if(!todo.done) 
    { 
     notDonedTodos.push(todo); 
    } 
}); 

$scope.todos = notDonedTodos; 
+0

ありがとうございます、あなたは素晴らしいです! – jvakuiler

18

forEachだけ配列の初期状態を知っているので、最初の呼び出しは、配列から項目を削除した場合でも、二回あなたのメソッドを呼び出しますので、これが起こっています。ただ、代わりにループしながら、簡単な操作を行います。

var i = $scope.todos.length; 
while (i--){ 
    if ($scope.todos[i].done){ 
     $scope.todos.splice(i, 1); 
    } 
} 
+0

このソリューションのトリックは、配列が逆順で処理され、配列の長さのボラティリティを無視できるということです。これは、従来のforループでも同様に有効です。 –

3

each反復の問題は、それがスキップされる反復を引き起こし配列から項目を削除していることです。 jQueryには、提供された無名関数によって決定される特定の基準に一致するすべての要素を返す素敵なgrepメソッドがあります。別の代替として、

var todos =[{id:1, done:false},{id:2, done:true},{id:3, done:true}]; 

function removeCompleted(todos){ 
    return $.grep(todos,function(todo){ 
     return todo.done == false; 
    }); 
} 

todos = removeCompleted(todos); 
console.log(todos); 

実施例http://jsfiddle.net/ktCEN/

Documentation

2

、あなたは自分のインデックスあなたがspliceを行うたびにデクリメントできます。例:

$scope.clearCompleted = function() { 
    angular.forEach($scope.todos, function(todo, i) { 
     if(todo.done) { 
      $scope.todos.splice(i, 1); 
      i--; 
     }; 
    }); 

    if($scope.todos.length == 0) { 
     $scope.isEmpty = true; 
    }; 
} 

これは、配列が変更されるたびに有効性を維持するようにインデックスを調整します。 angular.forEachを使用することはできますが、2つの配列のコピーで終わることはありません。

7

私が見つけた選択肢は、array.filterメソッドを使用することです。これは、オブジェクトキーに基づいて配列をフィルタリングする最も簡単な方法です。 IE8プロジェクト(貧乏人)で作業している場合は、この関数のためにpolyfillを追加する必要があります。これは、JavaScriptにとってかなり新しいことです。

Everything you need to know about javascript

回答コード:

$scope.clearCompleted = function() { 
    $scope.todos = $scope.todos.filter(function(item) { 
     return !item.done; 
    }); 
} 
+0

優れたソリューション – Clint