Skip to main content
 首页 » 编程设计

c#之Linq 获取并置相等对象的集合

2024年02月23日35mfryf

下面的代码展示了我想要做什么:

public static IEnumerable<IEnumerable<T>> DoIt<T>(this IEnumerable<T> that) 
{ 
    if (that == null) 
        throw new ArgumentNullException(); 
 
    if (that.Count() > 1) 
    { 
        var result = new Collection<IEnumerable<T>>(); 
        var collection = new Collection<T>(); 
 
        collection.Add(that.ElementAt(0)); 
        for (int i = 1; i < that.Count(); ++i) 
        { 
            if (!that.ElementAt(i).Equals(that.ElementAt(i - 1))) 
            { 
                result.Add(collection); 
                collection = new Collection<T>(); 
            } 
 
            collection.Add(that.ElementAt(i)); 
        } 
 
        result.Add(collection); 
        return result; 
    } 
 
    return new Collection<IEnumerable<T>>() { that }; 
} 

如果没有合适的实现,我只会使用像那个那样的自定义实现。有什么方法可以用标准框架做同样的事情吗?

请您参考如下方法:

使用标准框架没有传统方法可以做到这一点。不过,您的解决方案确实存在一些问题。

  1. ElementAt(i) 的使用效率非常低,并且会导致 that 集合被迭代很多很多次。这可能会导致性能问题
  2. Count 的使用也可能代价高昂,因为它可能导致that 的完整枚举
  3. 与大多数 LINQ 方法不同,它不使用延迟执行。要解决此问题,您需要使用 yield return 样式的解决方案。

这里有一个替代方案

public static IEnumerable<IEnumerable<T>> DoIt<T>(this IEnumerable<T> that) { 
  using (var e = that.GetEnumerator()) { 
    if (!e.MoveNext()) { 
      yield break; 
    } 
 
    bool hasMore; 
    do { 
      var item = e.Current; 
      var list = new List<T>(); 
      list.Add(item); 
 
      hasMore = e.MoveNext(); 
      while (hasMore && item.Equals(e.Current)) { 
        list.Add(e.Current); 
        hasMore = e.MoveNext(); 
      } 
 
      yield return list; 
    } while (hasMore); 
  } 
}