[英]How to use LINQ or Lambda instead of nested and multiple foreach statements
How can I use LINQ or Lambda instead of nested and multiple foreach statements. 如何使用LINQ或Lambda代替嵌套和多个foreach语句。
I want to use a better syntax than nested foreach statements to overwrite the initial list with items from the second list. 我想使用比嵌套的foreach语句更好的语法来用第二个列表中的项目覆盖初始列表。
In the code below: 在下面的代码中:
Use the items in secondList where Value was the same (Yellow) New initialList list should include (Green and Yellow) 使用secondList中值相同的项目(黄色)新的initialList列表应包括(绿色和黄色)
static void Main(string[] args) { int useProd = 2; int useDomain = 0; var person1 = new Person() { prodId = 1, Value = "foo", domainId = 0, Name = "Red" }; var person2 = new Person() { prodId = 1, Value = "bar", domainId = 0, Name = "Green" }; var person3 = new Person() { prodId = 1, Value = "foo", domainId = 1, Name = "Yellow" }; var initialList = new List<Person>(); initialList.Add(person1); initialList.Add(person2); var secondList = new List<Person>(); secondList.Add(person3); List<Person> personsToRemove = new List<Person>(); List<Person> personsToUpdate = new List<Person>(); foreach (var pers1 in initialList) { foreach (var pers2 in secondList) { if (pers1.Value == pers2.Value) { personsToRemove.Add(pers1); personsToUpdate.Add(pers2); } } } foreach (var remPers in personsToRemove) { initialList.Remove(remPers); } foreach (var updPers in personsToUpdate) { initialList.Add(updPers); } foreach (var item in initialList) { Console.WriteLine(String.Format("Value: {0}, prodId: {1}, domainId: {2}, Name: {3}", item.Value, item.prodId, item.domainId, item.Name)); } Console.ReadKey(); } public class Person { public int prodId { get; set; } public string Value { get; set; } public int domainId { get; set; } public string Name { get; set; } }
Your nested loops are most efficiently represented with a join
. 您的嵌套循环最有效地用
join
表示。 In addition, it would be helpful efficiency-wise to not have to do a linear-search on the entire list just to remove an element and then to add a new one in. There is an overload of Enumerable.Select()
we can use to embed the item index in the result, so that the element can simply be replaced directly. 此外,从效率角度考虑,不必在整个列表上进行线性搜索即可删除一个元素,然后再添加一个新元素。这对我们
Enumerable.Select()
有很多重载将项目索引嵌入到结果中,以便可以简单地直接替换元素。
Putting it all together, it looks like this: 放在一起,看起来像这样:
var join = from p1 in initialList.Select((p, i) => new { Person = p, Index = i })
join p2 in secondList on p1.Person.Value equals p2.Value
select new { Index = p1.Index, Replacement = p2 };
foreach (var item in join.ToList())
{
initialList[item.Index] = item.Replacement;
}
The above code replaces the original code starting with the declarations of the personsToRemove
and personsToUpdate
lists, and the first three foreach
loops (ie all but the one that displays the final result). 上面的代码替换了原始代码,从
personsToRemove
和personsToUpdate
列表的声明开始,以及前三个foreach
循环(即显示最终结果的循环除外)。
Notes: 笔记:
initialList
, the code synthesizes an anonymous type containing the Person
instance and the index of that instance in the list. initialList
合成一个匿名类型,该类型包含Person
实例和该实例在列表中的索引。 join
clause pairs up all of the items from each list where the Value
properties are equal. join
子句将每个列表中Value
属性相等的所有项配对。 Important: if there are multiple elements in either list with the same Value
property, they are each paired with every other element in the other list having that same Value
. 重要提示:如果任一列表中有多个具有相同
Value
属性的元素,则它们将与另一个列表中具有相同Value
每个其他元素配对。 Ie if initialList
has two elements having the Value
of "foo" and secondList
has three such elements, you will wind up with six elements in the resulting join. 也就是说,如果
initialList
具有两个要素Value
“富”和secondList
有三个这样的元素,你会风与中产生的加入六大要素。 Your question does not define whether this is possible, nor what you would want to happen if it were, so I've just ignored that possibility here. 您的问题并没有定义这是否可能,如果可能,您将要发生什么,因此在这里我只是忽略了这种可能性。 :)
:)
join
result is projected to a new anonymous type containing the index of the element to be replaced, and the new value. join
结果投影到一个新的匿名类型,其中包含要替换的元素的索引和新值。 ToList()
. ToList()
查询结果。 This is necessary because the join is otherwise deferred and modifying the initialList
would invalidate the query. initialList
将使查询无效。 foreach
all that the code then needs to do is assign to the appropriate index position in the list the replacement value determined by the query. foreach
所有的代码,然后需要做的是分配给替换值确定由查询列表中相应的索引位置。 You can use Generics as well. 您也可以使用泛型。 Below is the short code will work for you:
以下是适合您的简短代码:
initialList.ForEach(p =>
{
if (secondList.Any(sp => sp.Value == p.Value))
{
initialList.Remove(p);
initialList.Add(secondList.Single(spu => spu.Value == p.Value));
};
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.