如何比较两个List并修改其中一个List的指定属性?
问题描述
我有两个List<Data>,需要对比这两个列表:如果selectedInstance中的项在firstInstance里存在相同的AccountNo,就把firstInstance对应项的Selected布尔属性从false改为true。我尝试用IEnumerator编写代码,但没得到预期结果。
预期输出:
List<Data> firstInstance = new List<Data> { new Data { AccountNo = 1001,AccountName="AccountName1",BranchName="BranchName1", Selected = false }, new Data { AccountNo = 1101,AccountName="AccountName2",BranchName="BranchName2", Selected = true}, new Data { AccountNo = 1051,AccountName="AccountName3",BranchName="BranchName3", Selected = false }, new Data { AccountNo = 1991,AccountName="AccountName4",BranchName="BranchName4", Selected = true}, new Data { AccountNo = 1234,AccountName="AccountName5",BranchName="BranchName5", Selected = false }, };
我尝试的代码:
static class Program { static void Main(string[] args) { List<Data> firstInstance = new List<Data> { new Data { AccountNo = 1001,AccountName="AccountName1",BranchName="BranchName1", Selected = false }, new Data { AccountNo = 1101,AccountName="AccountName2",BranchName="BranchName2", Selected = false }, new Data { AccountNo = 1051,AccountName="AccountName3",BranchName="BranchName3", Selected = false }, new Data { AccountNo = 1991,AccountName="AccountName4",BranchName="BranchName4", Selected = false }, new Data { AccountNo = 1234,AccountName="AccountName5",BranchName="BranchName5", Selected = false }, }; List<Data> selectedInstance = new List<Data> { new Data { AccountNo = 1991,AccountName="AccountName4",BranchName="BranchName4", Selected = true }, new Data { AccountNo = 1101,AccountName="AccountName2",BranchName="BranchName2", Selected = true } }; firstInstance.CheckActive(selectedInstance); } static void CheckActive(this List<Data> firstInstance, List<Data> selectedInstance) { using (IEnumerator<Data> firstEnumerator = firstInstance.GetEnumerator(), secondEnumerator = selectedInstance.GetEnumerator()) { while (true) { if (!firstEnumerator.MoveNext() || !secondEnumerator.MoveNext()) break; if (firstEnumerator.Current.AccountNo == secondEnumerator.Current.AccountNo) firstEnumerator.Current.Selected = true; } } } } class Data { public int AccountNo { get; set; } public string AccountName { get; set; } public string BranchName { get; set; } public bool Selected { get; set; } }
问题原因
你用IEnumerator同时遍历两个列表的写法逻辑错误:这种方式只会对比两个列表相同索引位置的元素,而不会在firstInstance中全局查找selectedInstance里的AccountNo。比如selectedInstance第一个元素的AccountNo是1991,而firstInstance里1991在第4个位置,这种遍历方式根本不会把这两个元素对应起来,而且只要其中一个列表遍历到末尾就会停止,自然无法得到预期结果。
正确解决方案
方法1:使用HashSet优化查找效率
先把selectedInstance里所有的AccountNo提取到HashSet中(HashSet的查找时间复杂度是O(1),比遍历列表快很多),然后遍历firstInstance,逐个检查AccountNo是否在HashSet中,是的话就设置Selected为true:
static void CheckActive(this List<Data> firstInstance, List<Data> selectedInstance) { // 提取选中的AccountNo到HashSet var selectedAccountNos = new HashSet<int>(selectedInstance.Select(d => d.AccountNo)); foreach (var item in firstInstance) { if (selectedAccountNos.Contains(item.AccountNo)) { item.Selected = true; } } }
方法2:嵌套循环(适合小规模数据)
如果数据量很小,也可以直接用嵌套循环遍历两个列表,找到匹配的AccountNo就修改属性:
static void CheckActive(this List<Data> firstInstance, List<Data> selectedInstance) { foreach (var firstItem in firstInstance) { foreach (var selectedItem in selectedInstance) { if (firstItem.AccountNo == selectedItem.AccountNo) { firstItem.Selected = true; break; // 找到匹配项后跳出内层循环,避免重复检查 } } } }
方法3:LINQ写法(简洁版)
用LINQ的Any方法也可以实现,代码更简洁:
static void CheckActive(this List<Data> firstInstance, List<Data> selectedInstance) { foreach (var item in firstInstance) { item.Selected = selectedInstance.Any(s => s.AccountNo == item.AccountNo); } }
以上三种方法都能正确实现需求,其中方法1的性能最优,适合数据量大的场景。
内容的提问来源于stack exchange,提问作者Abhishek
相关产品推荐
相关产品推荐

