84

假设我有一个来自表的一些列值的列表,如何删除空字符串和重复值。请看以下代码:

List<string> dtList = dtReportsList.AsEnumerable().Select(dr => dr.Field<string>("column1")).ToList();

这是我刚刚编写的代码,但是 Amiram 的代码更加优雅,所以我会选择这个答案,这就是我的做法:

DataTable dtReportsList = someclass.GetReportsList();

        if (dtReportsList.Rows.Count > 0)
       { 
           List<string> dtList = dtReportsList.AsEnumerable().Select(dr => dr.Field<string>("column1")).ToList();
           dtList.RemoveAll(x=>x == "");
           dtList = dtList.Distinct().ToList();         

           rcboModule.DataSource = dtList;
           rcboModule.DataBind();               
           rcboModule.Items.Insert(0, new RadComboBoxItem("All", "All"));
       }
4

4 回答 4

217
dtList  = dtList.Where(s => !string.IsNullOrWhiteSpace(s)).Distinct().ToList()

我假设空字符串和空格就像null。如果不是,您可以使用IsNullOrEmpty(允许空格),或者s != null

于 2012-08-08T14:47:40.950 回答
10

Amiram 的回答是正确的,但实现的 Distinct() 是 N 2操作;对于列表中的每个项目,算法将其与所有已处理的元素进行比较,如果它是唯一的则返回它,否则忽略它。我们可以做得更好。

排序列表可以在线性时间内进行重复数据删除;如果当前元素等于前一个元素,则忽略它,否则返回它。排序是 NlogN,所以即使必须对集合进行排序,我们也会得到一些好处:

public static IEnumerable<T> SortAndDedupe<T>(this IEnumerable<T> input)
{
   var toDedupe = input.OrderBy(x=>x);

   T prev;
   foreach(var element in toDedupe)
   {
      if(element == prev) continue;

      yield return element;
      prev = element;      
   }
}

//Usage
dtList  = dtList.Where(s => !string.IsNullOrWhitespace(s)).SortAndDedupe().ToList();

这将返回相同的元素;他们只是排序。

于 2012-08-08T15:01:00.640 回答
6

为了简化Amiram Korach 的解决方案:

dtList.RemoveAll(s => string.IsNullOrWhiteSpace(s))

无需使用 Distinct() 或 ToList()

于 2020-10-27T10:54:52.643 回答
1

Amiram Korach 解决方案确实很整洁。为了多功能性,这里有一个替代方案。

var count = dtList.Count;
// Perform a reverse tracking.
for (var i = count - 1; i > -1; i--)
{
    if (dtList[i]==string.Empty) dtList.RemoveAt(i);
}
// Keep only the unique list items.
dtList = dtList.Distinct().ToList();
于 2012-08-08T15:01:52.543 回答