我编写了一个从开放API获取数据的小程序。从这些对象生成对象,并将这些对象列表与数据库中的某些数据也在对象列表中进行比较
问题是每个循环完成时foreach循环越来越慢。
你会看到我不是专业人士。我还是初学者,我找不到解决方案。
这是一张会发生什么的图片:
非常感谢每一个提示。
这是我的代码:
public static List<Player> comparePlayersWithDB(Boolean difference, List<Player> jsonPlayer, List<Player> dBPlayer)
{
List<Player> result = new List<Player>();
if (!difference)
{
Console.WriteLine("Searching for new Players -- " + DateTime.Now.ToLocalTime());
}
else
{
Console.WriteLine("Searching for differences in Players -- " + DateTime.Now.ToLocalTime());
}
DateTime startTime = DateTime.Now;
double statPercent = 0;
var count = jsonPlayer.Count;
int playerCount = 0;
int lastPlayerCount = 0;
double multiplier = ((double)100 / count);
int nextStep = 10;
Console.WriteLine(" 0% ...... -- " + DateTime.Now.ToLocalTime());
foreach (Player currentJson in jsonPlayer)
{
playerCount += 1;
//Message to User
if (statPercent >= nextStep)
{
int secondsGone = (DateTime.Now - startTime).Seconds;
if (secondsGone == 0)
{
secondsGone += 1;
}
int playersEachSecons = (playerCount - lastPlayerCount) / secondsGone;
Console.WriteLine(" " + (int)statPercent + "% (" + playerCount + "/" + count + ")......Speed: " + playersEachSecons + " Player/Second -- " + DateTime.Now.ToLocalTime());
lastPlayerCount = playerCount;
nextStep += 10;
startTime = DateTime.Now;
}
if (dBPlayer.Exists(x => x.Name == currentJson.Name))
{
if (difference)
{
//Check for differences
Player inDB = dBPlayer.Find(y => y.Name == currentJson.Name);
if (inDB.XP != currentJson.XP || inDB.RP != currentJson.RP || inDB.Guild != currentJson.Guild)
{
result.Add(currentJson);
}
}
}
// If currentPlayer not exists
else
{
//and we are looking only for new Players
if (!difference)
{
result.Add(currentJson);
}
}
statPercent += multiplier;
}
return result;
}
答案 0 :(得分:1)
尝试在dBPlayer
之前foreach
创建一个查找。
var playerLookup = dbPlayer.ToLookup(p => p.Name);
然后你可以做
if (playerLookup.Contains(currentJson.Name))
{
if (difference)
{
//Check for differences
Player inDB = playerLookup[currentJson.Name].First();
if (inDB.XP != currentJson.XP || inDB.RP != currentJson.RP || inDB.Guild != currentJson.Guild)
{
result.Add(currentJson);
}
}
}
这比在Exists
列表中执行Find
然后dbPlayer
执行速度更快。或者,如果您确定不会有任何重复的名称,则可以使用ToDictionary
代替。
答案 1 :(得分:0)
当您调用Exists
时,必须循环完整的dbPlayers列表(在最坏的情况下,没有匹配的条目)。然后,如果是匹配,则调用dbPlayer.Find()
,这基本上会再次完成整个事情。最好调用Find()
并将结果保存在变量中。如果变量为null
,则表示没有匹配项,否则您已经拥有了所请求的条目。
您仍有一个缺点,即您每次都有dbPlayer
循环遍历所有值的风险,这会导致dbPlayer
条目越多,性能越差。
我建议将dbPlayer
列表转换为Dictionary
,其中每个列表条目的Name
成为字典的键,如下所示:
using System.Linq;
[...]
var dbPlayerDict = dbPlayer.ToDictionary(x => x.Name);
这将允许您通过调用TryGetValue()
来查找现有玩家,无论需要搜索多少条目,它都具有相同的性能,使您的代码看起来像这样:
Player inDB;
if (dBPlayerDict.TryGetValue(currentJson.Name, out inDB))
{
if (difference)
{
//Check for differences
if (inDB.XP != currentJson.XP || inDB.RP != currentJson.RP || inDB.Guild != currentJson.Guild)
{
result.Add(currentJson);
}
}
}
如果多个玩家可以使用相同的名称,那么最好使用Lookup
类,如@ juharr的回答中所述。