我写了一个代码,基本上比较两个列表,并检查它们的属性,名为TransactionID,如果旧列表中不存在TransactionID,它将被添加到只包含旧项的新列表中。
所以列表是:
// list named: prepared - contains all old and new items
// UserTransactions from DB - list - contains only old transactions
现在,我比较这两个列表,看看准备的列表中是否有一些项目不在数据库的用户事务列表中,如下所示:
var ListDoAdd = prepared.Where((i) => ctx.EbayUserTransactions.Where(x => x.SearchedUserID == updatedUser.SearchedUserID).ToList().FindIndex((el) => el.TransactionID == i.TransactionID) == -1).ToList();
现在,ListDoAdd最终包含DB中丢失的所有项。
当我处理大量记录时,这种方法效率很低。
我想我可以做的是首先将特定用户的所有事务加载到内存中,如下所示:
var oldList = ctx.UserTransactions.Where(x => x.SearchedUserID == updatedUser.SearchedUserID).ToList()
然后在运行时比较这两个列表以加快速度,而不是逐一检查每一项,我上面展示的方法现在没有这样做?
So now I have:
prepared list
and
oldList
现在我只需要找出最快的方法来比较这两个列表并找到缺失的项目。。。
有人能帮我吗?
第页。S.伙计们,如果我要做多线程,唯一可能的方法就是使用PLINQ,不是吗?
如果这两个列表都加载在内存中,我建议使用带有自定义比较器的set方法,比如
public class UserTransactionByIdComaprer : IEquialityComparer<UserTransaction>
{
pulic static readonly IEqualityComparer<UserTransaction> Instance = new UserTransactionByIdComaprer();
public bool Equals(UserTransaction x, UserTransaction y)
{
return x.TransactionId == y.TransactionId;
}
public int GetHashCode(UserTransaction x)
{
return x.TransactionId.GetHashCode();
}
}
var prepared = ....
var old = ...
var diff = prepared.Except(old, UserTransactionByIdComaprer.Instance); // this are all that are not present in the old list
使用set函数会给您带来更好的性能,主要是因为它只会枚举集合一次。更多信息:设置操作
关于并行:您可以非常容易地并行化查询。
var diff = prepared.Except(old, UserTransactionByIdComaprer.Instance)
.AsParallel()
.WithDegreeOfParallelism(2)
我建议你做一些性能测试。对于带有15k元素的系列,我会在没有并行元素的情况下为您带来一些性能提升。
注意事项:如果并行和非并行版本的时间相似,并且您在高负载的服务器上运行该程序,其中每个线程可能都很重要,我建议使用非并行版本。
如果我很理解,您想比较两个列表。要做到这一点,通常我们通过LINQ左联接来实现。请参阅以下代码:
from p in context.ParentTable
join c in context.ChildTable on p.ParentId equals c.ChildParentId into j1
from j2 in j1.DefaultIfEmpty()group j2 by p.ParentId into grouped
select new { ParentId = grouped.Key, Count = grouped.Count() }
我希望对你有用
如果您有两个类型的集合,其中包含一个名为TransactionID
的属性,并且您想查找第二个集合中缺少的一个集合的所有元素,则可以使用Enumerable.Except()
。
在使用Enumerable.Except()
之前,您需要实现IEqualityComparer<Transaction>
,因为它用于比较集合中的项。
假设您的事务类如下所示:
class Transaction
{
public int TransactionID;
}
那么IEqualityComparer<Transaction>
的实现将是:
class Comparer : IEqualityComparer<Transaction>
{
public bool Equals(Transaction x, Transaction y)
{
return x.TransactionID == y.TransactionID;
}
public int GetHashCode(Transaction obj)
{
return obj.TransactionID.GetHashCode();
}
}
考虑到这一点,你可以找到丢失的物品,比如:
var missing = oldList.Except(newList, new Comparer());
例如:
static void Main()
{
var oldList = new List<Transaction>
{
new Transaction{ TransactionID = 1 },
new Transaction{ TransactionID = 2 },
new Transaction{ TransactionID = 3 },
new Transaction{ TransactionID = 4 },
new Transaction{ TransactionID = 5 },
};
var newList = new List<Transaction>
{
new Transaction{ TransactionID = 2 },
new Transaction{ TransactionID = 4 },
};
var missing = oldList.Except(newList, new Comparer());
foreach (var item in missing) // This prints "1", "3" and "5".
{
Console.WriteLine(item.TransactionID);
}
}
[EDIT]这是完整的可编译应用程序。
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace ConsoleApplication1
{
class Transaction
{
public int TransactionID;
}
class Comparer : IEqualityComparer<Transaction>
{
public bool Equals(Transaction x, Transaction y)
{
return x.TransactionID == y.TransactionID;
}
public int GetHashCode(Transaction obj)
{
return obj.TransactionID.GetHashCode();
}
}
class Program
{
static void Main()
{
var oldList = createList(0, 1, 50000000);
var newList = createList(0, 2, 50000000/2);
var comparer = new Comparer();
Stopwatch sw = new Stopwatch();
for (int i = 0; i < 4; ++i)
{
sw.Restart();
var missing = oldList.Except(newList, comparer);
Console.WriteLine(missing.Count());
Console.WriteLine("Linq: " + sw.Elapsed);
sw.Restart();
missing = oldList.Except(newList, comparer).AsParallel();
Console.WriteLine(missing.Count());
Console.WriteLine("Plinq: " + sw.Elapsed);
}
}
static List<Transaction> createList(int startingId, int idIncrement, int count)
{
var result = new List<Transaction>(count);
for (int i = 0; i < count; ++i, startingId += idIncrement)
result.Add(new Transaction {TransactionID = startingId});
return result;
}
}
}