【问题标题】:Help with F#: "Collection was modified"F# 帮助:“集合已修改”
【发布时间】:2010-12-15 19:56:57
【问题描述】:

我对这里的 F# 很陌生,我在 F# 中遇到了“Collection was modified”的问题。我知道当我们在迭代集合的同时修改(添加/删除)它时,这个问题很常见。而stackoverflow中之前的线程也指向了这一点。

但就我而言,我正在研究 2 个不同的集合: 我有 2 个收藏:

  • originalCollection 我要从中删除内容的原始集合
  • colToRemove 包含我要删除的对象的集合

下面是代码:

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

我收到以下运行时错误: + $exception {System.InvalidOperationException:集合已修改;枚举操作可能无法执行。 在 System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource 资源) 在 System.Collections.Generic.List1.Enumerator.MoveNextRare() at System.Collections.Generic.List1.Enumerator.MoveNext() 在 Microsoft.FSharp.Collections.IEnumerator.next@174[T](FSharpFunc2 f, IEnumerator1 e,FSharpRef1 started, Unit unitVar0) at Microsoft.FSharp.Collections.IEnumerator.filter@169.System-Collections-IEnumerator-MoveNext() at Microsoft.FSharp.Collections.SeqModule.Iterate[T](FSharpFunc2 操作,IEnumerable`1 源)

这是代码块:

        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 -> ()

谢谢!

注意:这里是在单线程环境下工作,因此不存在可能导致此异常的多线程问题。

【问题讨论】:

    标签: f#


    【解决方案1】:

    这里的问题是colToRemove不是一个独立的集合,而是集合originalCollection的一个投影。因此更改originalCollection 会更改迭代期间不允许的投影。上述代码的 C# 等效代码如下

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

    您可以通过List.ofSeq 方法将colToRemove 设为独立集合来解决此问题。

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

    【讨论】:

      【解决方案2】:

      我不会尝试删除,因为您正在修改一个集合,而是尝试像这样创建另一个集合:

      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
      

      【讨论】:

        猜你喜欢
        • 2016-03-06
        • 2010-11-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-11
        • 1970-01-01
        相关资源
        最近更新 更多