我在SO上搜索了一个解决方案,但我找不到它,所以我提出了这个新问题。
我有两个不同类的2个列表。
头等舱:
public class Class1
{
public int C1Property1 {get;set;}
public int C1Property2 {get;set;}
public int C1Property3 {get;set;}
}
第二节课:
public class Class2
{
public int C2Property1 {get;set;}
public int C2Property2 {get;set;}
public int C2Property3 {get;set;}
}
我有两个类的列表:
List<Class1> Class1List = new List<Class1>();
List<Class2> Class2List = new List<Class2>();
现在对我来说很困难:两个类中的两个属性具有相同的值,但具有不同的名称:即C1Property1 = C2Property1
和C1Property2 = C2Property2
。列表Class1List
的属性C1Property1
为空,我需要使用Class2List
中的属性填充它。我使用以下代码执行此操作:
foreach(var element1 in Class1List)
{
foreach(var element2 in Class2List)
{
if(element2.C2Property2 == element1.C1Property2)
{
element1.C1Property1 = element2.C2Property1;
}
}
}
这个解决方案是我的意图,但非常难看,我有2个foreach循环,可能很慢(列表可以包含超过10 000个元素)。在示例类中,我只编写了3个属性来显示它是如何工作的,但最初它每个都有~20个属性,而且只有2个属性相同。我可以更快更有效地完成这项工作吗?有些LinQ也许吧?对不起,我无法显示更多代码。我希望你能理解我的要求。
我只需要从Class2List
获取一个属性,并且仅当列表中的一个参数相同时才将其放在Class1List
上。
在我的第二次尝试中,我使用了类似的东西:
foreach (var element1 in Class1List)
{
foreach (var element2 in Class2List.Where(element2 => element2.C2Property2 == element1.C1Property2 ))
{
element2.C2Property2 = element1.C1Property2;
break;
}
}
这应该更快但仍然看起来很丑陋
答案 0 :(得分:3)
所以我在这里有三个选择:
Class1List.ForEach(element1 =>
{
Class2 element2 = Class2List.FirstOrDefault(e2 => e2.C2Property2 == element1.C1Property2);
if (element2 != null) element1.C1Property1 = element2.C2Property1;
});
这使得我的机器4.58s在每个列表中有20000个元素。虽然代码看起来(对我来说)好一点,但这与你的代码有效。
使用字典通过哈希访问Class2
元素非常有效:
Dictionary<int, Class2> dictionary = Class2List.GroupBy(e2 => e2.C2Property2, e2 => e2).Select(elements => elements.First()).ToDictionary(e2 => e2.C2Property2, e2 => e2);
Class1List.ForEach(element1 =>
{
if (dictionary.ContainsKey(element1.C1Property2))
element1.C1Property1 = dictionary[element1.C1Property2].C2Property1;
});
这使得我的机器在每个列表中的20000个元素为0.00878s。
如果您的数据真的很大,您可以考虑使用Parallel.ForEach
Dictionary<int, Class2> dictionary =
Class2List.GroupBy(e2 => e2.C2Property2, e2 => e2).Select(elements => elements.First()).ToDictionary(e2 => e2.C2Property2, e2 => e2);
Parallel.ForEach(Class1List, element1 =>
{
if (dictionary.ContainsKey(element1.C1Property2))
element1.C1Property1 = dictionary[element1.C1Property2].C2Property1;
});
但是每个列表中只有20000个元素,这使我的机器比非并行版本更长(0.0197s)。
答案 1 :(得分:1)
弄清楚这是一件非常有趣的事情,但我觉得这样的事情可能有用:
Class1List.ForEach(c1 =>
c1.C1Property1 = Class2List.Where(c2 => c2.C2Property2 == c1.C1Property2)
.Select(r => r.C2Property1)
.FirstOrDefault());
这是一个测试类:
using System;
using System.Collections.Generic;
using System.Linq;
namespace SO_Test
{
public class ObjectA
{
public int Property1 { get; set; }
public int? Property2 { get; set; }
public override string ToString()
{
return String.Format("({0}, {1})", Property1, Property2);
}
}
public class ObjectB
{
public int Property1 { get; set; }
public int? Property2 { get; set; }
public override string ToString()
{
return String.Format("({0}, {1})", Property1, Property2);
}
}
class Program
{
static void Main()
{
var listA = new List<ObjectA>
{
new ObjectA { Property1 = 5, Property2 = null },
new ObjectA { Property1 = 16, Property2 = null },
new ObjectA { Property1 = 9, Property2 = null },
new ObjectA { Property1 = 38, Property2 = null }
};
var listB = new List<ObjectB>
{
new ObjectB { Property1 = 5, Property2 = 1 },
new ObjectB { Property1 = 9, Property2 = 2 },
new ObjectB { Property1 = 16, Property2 = 3 }
};
Console.WriteLine("BEFORE");
Console.WriteLine("ListA: {0}", String.Join(", ", listA));
Console.WriteLine("ListB: {0}", String.Join(", ", listB));
listA.ForEach(a =>
a.Property2 = listB.Where(b => b.Property1 == a.Property1)
.Select(r => r.Property2)
.FirstOrDefault());
Console.WriteLine("AFTER");
Console.WriteLine("ListA: {0}", String.Join(", ", listA));
Console.WriteLine("ListB: {0}", String.Join(", ", listB));
Console.ReadLine();
}
}
}
输出:
BEFORE
ListA: (5, ), (16, ), (9, ), (38, )
ListB: (5, 1), (9, 2), (16, 3)
AFTER
ListA: (5, 1), (16, 3), (9, 2), (38, )
ListB: (5, 1), (9, 2), (16, 3)