在具有linq的foreach中从集合中删除
本文关键字:集合 删除 foreach linq | 更新日期: 2023-09-27 18:02:57
据我所知,这似乎不是一个安全的做法…
我在我的列表对象上有一个foreach循环,我正在遍历它。在foreach循环中,我通过Id查找记录。一旦我有了那个Id返回的记录的新列表,我就进行一些解析并将它们添加到一个新列表中。
我想做的是不要多次遍历同一个Id。所以我的想法是把它从原来的列表中删除。然而,这会导致一个错误…我知道为什么。
我的问题是……有什么安全的办法吗?还是我应该稍微调整一下我的思维过程?我想知道是否有人对如何解决这个问题有任何经验或想法?下面是一小段伪代码:
_myList.ForEach(x =>
{
List<MyModel> newMyList = _myList.FindAll(y => y.SomeId == x.SomeId).ToList();
//Here is where I would do some work with newMyList
//Now I am done... time to remove all records with x.SomeId
_myList.RemoveAll(y => y.SomeId == x.SomeId);
});
我知道_myList.RemoveAll(y => y.SomeId == x.SomeId);
是错误的,但从理论上讲,这就是我想要的。
我还玩弄了将使用过的SomeId
推到idList
然后每次检查它的想法,但这似乎很麻烦,并且想知道是否有更好的方法来处理我想要做的事情。
对不起,如果我没有解释得很好。如果有任何问题,请随意评论,我将在需要的地方回答/编辑。
首先,由于这些原因,在示例中使用ForEach
不是一个好主意。
你认为为每个剩余的SomeId
遍历完整列表会有性能下降的想法是对的,但即使每次使列表变小,仍然需要对该子集进行另一次完整的迭代(如果它有效的话)。
正如在评论中指出的那样,SomeId
上的GroupBy
为您组织元素分组,并允许您有效地遍历给定SomeId
的每个子集,如下所示:
_myList.GroupBy(x => x.SomeId)
.Select(g => DoSomethingWithGroupedElements(g));
Jon Skeet有一组关于如何实现Linq扩展的优秀文章。我强烈建议您查看一下,以便更好地理解为什么这样做会更有效。
首先,foreach中的列表是不可变的,您不能添加或删除内容,也不能重写元素。有几种方法可以处理这种情况:
GroupBy
这是我要使用的方法。您可以根据所需的属性对列表进行分组,并通过以这种方式形成的igrouing进行迭代
var groups = list.GroupBy(x => x.yourProperty);
foreach(var group in groups)
{
//your code
}
不同属性列表
您也可以将属性保存在另一个列表中,并循环遍历该列表而不是原始列表
var propsList = list.Select(x=>x.yourProperty).Distinct();
foreach(var prop in propsList)
{
var tmpList = list.Where(x=>x.yourProperty == prop);
//your code
}
While循环这实际上是您最初想要的,但性能可能不是最佳的
while(list.Any())
{
var prop = list.First().yourProperty;
var tmpList = list.Where(x=>x.yourProperty == prop);
//your code
list.RemoveAll(x=>x.yourProperty == prop);
}