【问题标题】:Removing All Nulls From Collections从集合中删除所有空值
【发布时间】:2015-05-15 20:53:51
【问题描述】:

我不得不处理从我无法控制的数据源向我的应用程序抛出的数据集合。其中一些集合包含空值,我宁愿在它们命中我的代码时立即过滤掉它们,而不是将空值检查代码分散在各处。我想以可重用的通用方式执行此操作,并编写了此方法来执行此操作:

    public static void RemoveNulls<T>(this IList<T> collection) where T : class
    {
        for (var i = 0; i < collection.Count(); i++)
        {
            if (collection[i] == null)
                collection.RemoveAt(i);
        }
    }

我知道在具体的 List 类中有 RemoveAll() 方法,可以像这样使用:

collection.RemoveAll(x => x == null);

但是很多返回类型都是基于接口的(IList/IList ...)而不是具体类型。

【问题讨论】:

  • 请您详细说明为什么不能使用RemoveAll
  • 问题是什么?
  • 您编写的代码将不起作用,因为删除一个项目会将所有后续元素的索引向下移动 1。每次删除 null 时,您的代码都会跳过检查下一个元素。
  • 为什么投反对票!?!??
  • 这里的人都这么书呆子……

标签: c# .net collections


【解决方案1】:

您可以使用 LINQ 创建一个没有空值的集合副本,而不是从源集合中删除空值:

collection.Where(i => i != null).ToList();

扩展方法适用于任何 IEnumerable,包括 IList。

【讨论】:

  • 为什么不必要地复制整个集合?
  • @Jammer,您还可以删除 .ToList() 部分,以便它可以用作过滤器。如果您关心性能,请记住每个 RemoveAt 都会移动被删除项之后的所有列表项。因此,如果您从包含 1000 个项目的列表的开头删除 10 个项目,则至少 990 个项目将在内存中移动 10 次。
  • 它实际上可能会提高性能,因为从IList 中删除元素(至少使用像List&lt;T&gt; 这样的数组支持)会在每次执行时强制将所有后续元素复制到一个槽中.
  • @Jammer 我建议使用此解决方案与就地解决方案进行一些性能测试。如果您平均每个集合有两个以上的空值,我敢打赌这会运行得更快。
【解决方案2】:

您的方法不起作用,因为删除一个元素会导致所有后续元素的索引减少。如果您不想要 Linq 解决方案(这似乎最简单:请参阅 @alex 的答案),您应该向后迭代。

public static void RemoveNulls<T>(this IList<T> collection) where T : class
{
    for (var i = collection.Count-1; i >= 0 ; i--)
    {
        if (collection[i] == null)
            collection.RemoveAt(i);
    }
}

【讨论】:

  • “在这里测试效果很好” - 尝试更多的测试用例。特别是一个包含两个连续空值后跟一个非空值的集合。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-17
  • 2021-08-01
  • 1970-01-01
  • 2018-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多