从一个列表中选择全部,替换另一个列表上存在的值



几天前,我对SQL提出了同样的问题,但现在它出现在C#代码中

假设我们有这样一个类,用于保存不同的id/text对:

public class Text {
public int id { get; set; }
public string text { get; set; }
...
}

现在让我们填充一些数据,ListA获取了大量数据:

List<Text> ListA = new List<Text>{
new () {id = 1, text = "aaa1"},
new () {id = 2, text = "aaa2"},
new () {id = 3, text = "aaa3"},
new () {id = 4, text = "aaa4"},
new () {id = 5, text = "aaa5"},
new () {id = 6, text = "aaa6"},
};

ListB只得到一点点数据:

List<Text> ListB = new List<Text>{
new () {id = 4, text = "bbb4"},
new () {id = 5, text = "bbb5"},
};

现在我们正在寻找:

var result = ... // Some Linq or Lambda magic goes here
// and if we do:
foreach(var item in result){
Console.WriteLine(item.Id + " " + item.Text);
}
// Result will be:
1 : aaa1
2 : aaa2
3 : aaa3
4 : bbb4
5 : bbb5
6 : aaa6

您可以尝试在ListB:中查找id

var result = ListA
.Select(a => ListB.FirstOrDefault(b => b.id == a.id) ?? a);

对于ListA中的每个a,我们试图在ListB中找到对应的id(b.id == a.id(项。如果没有找到这样的项目,我们只返回ListA项目:?? item

在.Net 6的情况下,您可以使用过载的.FirstOrDefault版本(我们可以将a作为默认值传递(:

var result = ListA
.Select(a => ListB.FirstOrDefault(b => a.id == b.id, a));

首先将ListB转换为Dictionary可能更有效:var dictB = ListB.ToDictionary(x=> x.id)

然后你可以写

var result = ListA.Select(x => dictB.TryGetValue(x.id, out var b) ? b : x)

考虑的意见建议的UPD回放

一个选项是通过指定EqualityComparer来执行Union操作。如果订单很重要,您可以在最后执行OrderBy操作。

class TextIdComparer : EqualityComparer<Text> {
public override bool Equals(Text x, Text y) => x.id == y.id;
}
var result = ListB.Union(ListA, new TextIdComparer()).OrderBy(x => x.id)

最新更新