如何使用LINQ或Lambda代替嵌套和多个foreach语句。
我想使用比嵌套的foreach语句更好的语法来覆盖第二个列表中的项目的初始列表。
在下面的代码中:
使用secondList中的值,其中Value相同(黄色) 新的初始列表列表应包括(绿色和黄色)
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; }
}
答案 0 :(得分:1)
您的嵌套循环最有效地用join
表示。此外,在整个列表中不必进行线性搜索只是为了删除一个元素然后添加一个新元素,这将有助于提高效率。我们可以使用Enumerable.Select()
的重载将项索引嵌入到结果中,以便可以直接替换元素。
总而言之,它看起来像这样:
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;
}
上面的代码替换了原始代码,从personsToRemove
和personsToUpdate
列表的声明开始,以及前三个foreach
循环(即除了显示最终结果的所有循环外) )。
注意:
initialList
合成一个包含Person
实例的匿名类型以及列表中该实例的索引。join
子句将Value
属性相等的每个列表中的所有项配对。 重要提示:如果任一列表中有多个元素具有相同的Value
属性,则每个元素都与另一个列表中具有相同Value
的所有其他元素配对。即如果initialList
有两个元素Value
为&#34; foo&#34;并且secondList
有三个这样的元素,您将在结果连接中结束六个元素。你的问题没有定义这是否可能,也不是你想要发生什么,所以我在这里忽略了这种可能性。 :)
join
结果投射到一个新的匿名类型,其中包含要替换的元素的索引和新值。ToList()
来实现查询结果。这是必要的,因为否则延迟了连接,修改initialList
会使查询无效。foreach
中,代码需要做的就是为列表中的相应索引位置分配查询确定的替换值。答案 1 :(得分:1)
您也可以使用泛型。以下是适用于您的短代码:
initialList.ForEach(p =>
{
if (secondList.Any(sp => sp.Value == p.Value))
{
initialList.Remove(p);
initialList.Add(secondList.Single(spu => spu.Value == p.Value));
};
});