C# 有点像VLOOKUP
我试图合并两个不同对象的列表,其中一个特定字段(employeeID)等于另一个列表中的一个特定字段[0,0]。我的代码如下所示:C# 有点像VLOOKUP,c#,performance,C#,Performance,我试图合并两个不同对象的列表,其中一个特定字段(employeeID)等于另一个列表中的一个特定字段[0,0]。我的代码如下所示: int i = Users.Count() - 1; int i2 = oracleQuery.Count() - 1; for (int c = 0; c <= i; c++) { for (int d = 0; d <= i2; d++) { if (Users[c].getEmployeeID().ToString(
int i = Users.Count() - 1;
int i2 = oracleQuery.Count() - 1;
for (int c = 0; c <= i; c++)
{
for (int d = 0; d <= i2; d++)
{
if (Users[c].getEmployeeID().ToString() == oracleQuery[d][0,0].ToString())
{
Users[c].setIDMStatus(oracleQuery[d][0,1].ToString());
}
}
}
inti=Users.Count()-1;
int i2=oracleQuery.Count()-1;
对于(int c=0;c,可以使用连接:
请注意,如果getEmployeeId()
和oracleQuery的[0,0]
元素属于同一类型,则可以消除ToString()
调用。如果数据来自数据库,则可以在那里进行联接。否则,可以对两个列表进行排序,并进行合并联接,这将比现在更快
然而,自从C#引入LINQ以来,在代码中有很多方法可以做到这一点。只需查找使用LINQ加入/合并列表即可。就效率而言,我注意到的唯一一件事是使用Enumerable.Count()方法,该方法在for循环中再次显式循环之前枚举结果。我认为LINQ实现将摆脱通过结果来计算元素的过程
我不知道您对使用Linq查询表达式的感觉如何,但这是我最喜欢的:
var matched = from user in Users
join item in oracleQuery on user.getEmployeeID().ToString() equals item[0,0].ToString()
select new {user = user, IDMStatus = item[0,1] };
foreach (var pair in matched) {
pair.user.setIDMStatus(pair.IDMStatus);
}
您还可以使用嵌套的foreach循环(如果存在多个匹配项,并且多次调用set):
或者如果只有一个匹配是肯定的:
foreach (var user in Users) {
var match = oracleQuery.SingleOrDefault(item => user.getEmployeeID().ToString() == item[0,0].ToString())
if (match != null) {
user.setIDMStatus(match[0,1]);
}
}
我认为您编写的代码中没有任何真正的效率问题,但您可以将其与LINQ中的实现进行基准测试。我认为使用foreach
或LINQ查询表达式可能会使代码更易于阅读,但我认为效率没有问题。您还可以编写LINQ查询表达式关于使用Linq方法语法,正如在另一个答案中所做的那样。您的数据源是什么?Oracle RDBMS?p.s您正在寻找一个内部联接,它将构成db查询的一部分。我的数据源是Oracle db和Active Directory中的数据。感谢您提供的额外方法,Steve。我本来会做一个foreach语句,但出于某种原因(很可能是用户错误),它不想这样做。关于枚举的一些事情……尽管有一个奇怪的问题——查询中的select子句不会生成新对象而不是更改现有对象吗?(只是好奇。我真的不知道。)这将创建一个新的匿名对象,该对象包含对现有对象的引用(除非它们是值类型,在这种情况下,它们将被复制)。编译器可能会优化对象创建,但可能不会。最大的节省是在代码中循环两次…对Count()扩展方法的调用将枚举结果。然后,显式循环。使用Linq语法(my和Copsey的实现是相同的,只是我使用查询语法,Copsey使用方法语法),只有一个枚举。
foreach (var user in Users) {
foreach (var match in oracleQuery.Where(item => user.getEmployeeID().ToString() == item[0,0].ToString()) {
user.setIDMStatus(match[0,1]);
}
}
foreach (var user in Users) {
var match = oracleQuery.SingleOrDefault(item => user.getEmployeeID().ToString() == item[0,0].ToString())
if (match != null) {
user.setIDMStatus(match[0,1]);
}
}