【问题标题】:Filtering a List using contents of another List使用另一个列表的内容过滤列表
【发布时间】:2015-11-07 22:20:39
【问题描述】:

我有两个列表。我想使用第二个列表中的元素过滤掉第一个列表。所以我有这个代码:

 List<data> dataList = somedata;
 IEnumerable<Filter> filterList  = someFilterData;

然后我使用以下代码进行过滤:

foreach (var s in filterList)
{
     dataList =   dataList .Where(l => l.dataId!= s.Id).ToList();     
}

有人可以建议这是否是一种足够好的方法,或者我们如何使用其他技术使其更好。注意:列表可能会变大,因此我们也在考虑性能。

【问题讨论】:

  • 我会将过滤器 ID 放在哈希集中,然后执行一个 where,检查 dataId 是否不在哈希内

标签: c# list c#-4.0 filter


【解决方案1】:

也许,你需要这个

dataList = dataList.Where(l => !filterList.Select(x => x.Id).Contains(l.dataId)).ToList();

【讨论】:

  • filterList.Contains 在这里是错误的。 filterList 是过滤器列表,而不是 id 或 dataIds 列表
  • @AlwaysAProgrammer 感谢 cmets 关于错误
【解决方案2】:

我会这样做,使用 hashset 和一个 Where:

var filtIds = new HashSet<int>(filterList.Select(f=> f.Id));
var filteredDataList = dataList.Where(d=> !filtIds.Contains(d.dataId)).ToArray();

【讨论】:

  • +1 一种更有效的方法。但他想过滤列表,所以dataList=....ToList() 更合适。
【解决方案3】:

你需要的是只取那些在过滤器列表中找不到的项目。您可以使用循环以“老派”方式进行:

foreach (var listItem in dataList)
{
    foreach (var filterItem in filterList)
    {
        if (listItem == filterItem)
        {
            dataList.Remove(listItem);
            continue;
        }
    }
}

或者您可以使用 LINQ 进行过滤:

dataList.Where(d => filterList.All(f => f.Id != d.dataId))

【讨论】:

  • 我喜欢你的解决方案。它给出了正确的答案并且很干净。我的解决方案给出了正确的答案,但看起来很笨重。
  • @Mogsdad 感谢您提出这个问题。我阅读了您链接的 StackExchange 主题中的答案,我同意那里所说的内容。我将在今天或明天扩展我的答案。
【解决方案4】:
var filteredQuery =
                from d in dataList
                let filterListIds = from f in filterList
                    select f.Id
                where filterListIds.Contains(d.DataId) == false
                select d;

【讨论】:

  • @Mogsdad...我不明白你的评论。接受的答案也是纯代码。我的解决方案不是“试试这个”解决方案。我实际上已经对其进行了编码,并且可以正常工作。
  • @Mogsdad;感谢您的解释。你说的很有道理。
【解决方案5】:

聚会迟到了,但由于您的过滤器仅已知为 IEnumerable,因此重新修改过滤器以防止在每次迭代时从源中吸入可能不是一个好主意吗?我认为这就是@George 的意思。如果过滤器的来源在执行过程中发生了变化,它可能会不一致(并且在每次迭代中重新获取它们可能代价高昂):

var filterIds = filterList.Select( f=> f.Id ).ToArray( );

那么,“Not any”似乎(在我看来)比“All not equal”更能表达你的意思。

var results = dataList.Where( d=> !filterIds.Any( f=> d==f ) );

【讨论】:

    【解决方案6】:

    所以基本上你只想从第一个列表中删除所有出现在第二个列表中并且性能很重要的东西?

    我最喜欢Georges approach,如果列表越来越大,它是最有效的。但是List.RemoveAll也更高效:

    dataList.RemoveAll(d => filterList.Any(x => x.ID == d.DataID));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-13
      • 2011-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多