2010-12-15 12 views
1

ここではF#の新機能です。F#の "コレクションが変更されました"という問題が発生しました。私はこの問題が、同時にコレクションを変更(追加/削除)しながらコレクションを繰り返すときによくあることを知っています。また、stackoverflowの以前のスレッドもこれを指しています。F#のヘルプ: "コレクションが変更されました"

しかし、私の場合、私は2つの異なるセットに取り組んでいます:

  • originalCollection私はcolToRemoveに
  • にコレクションをものを削除する元のコレクション: 私は2つのコレクションを持っています削除したいオブジェクトが含まれています

以下はコードです:

Seq.iter (fun input -> ignore <| originalCollection.Remove(input)) colToRemove 

そして私だ、次のランタイムエラー: + $例外{のSystem.InvalidOperationException:コレクションが変更されました。列挙操作が実行されないことがあります。 [email protected] [T](FSharpFunc 2 f, IEnumerator 1つのEのSystem.Collections.Generic.List 1.Enumerator.MoveNextRare() at System.Collections.Generic.List 1.Enumerator.MoveNext() でSystem.ThrowHelper.ThrowInvalidOperationException(ExceptionResourceリソース) で

 match newCollection with 
     | Some(newCollection) -> 

      // compare newCollection to originalCollection. 
      // If there are things that exist in the originalCollection that are not in the newCollection, we want to remove them 
      let colToRemove = Seq.filter (fun input -> Seq.exists (fun i -> i.id = input.id) newCollection) originalCollection 
      Seq.iter (fun input -> ignore <| originalCollection.Remove(input)) colToRemove 

     | None ->() 

ありがとう:、ここ

FSharpRef 1 started, Unit unitVar0) at [email protected]ctions-IEnumerator-MoveNext() at Microsoft.FSharp.Collections.SeqModule.Iterate[T](FSharpFunc 2アクション、IEnumerable`1ソース)は、コードの塊です!

注:ここではシングルスレッド環境で作業しているため、この例外が発生する可能性のあるマルチスレッドの問題はありません。

答えて

5

ここでの問題は、colToRemoveは独立したコレクションではなく、コレクションoriginalCollectionの投影です。したがって、originalCollectionを変更すると、反復中に許可されない投影が変更されます。上記のコードのC#の同等のは、あなたがList.ofSeqメソッドを介してcolToRemove独立したコレクションを作ることによってこの問題を解決することができ、次の

var colToRemove = originalCollection 
    .Where(input -> newCollection.Any(i -> i.id == input.id)); 
foreach (var in input in colToRemove) { 
    originalCollection.Remove(input); 
} 

です。

let colToRemove = 
    originalCollection 
    |> Seq.filter (fun input -> Seq.exists (fun i -> i.id = input.id) newCollection) originalCollection 
    |> List.ofSeq 
1

私はあなたのコレクションを修正しているので、削除をしようとするが、代わりにそのような別のコレクションを作成しようとしないでしょう。

let foo() = 

    let orig = [1;2;3;4] 
    let torem = [1;2] 

    let find e = 
     List.tryFind (fun i-> i = e) torem 
     |> function 
     | Some _-> true 
     | None -> false 

    List.partition (fun e -> find e) orig 
    //or 
    List.filter (fun e-> find e) orig 

HTH

関連する問題