#c# #asp.net #linq #optimization
#c# #asp.net #linq #оптимизация
Вопрос:
Я создаю список пользователей. у каждого пользователя есть полное имя. Я сравниваю пользователей по полному имени.
я беру DataTable с пользователями из старой базы данных и анализирую их в объект ‘User’. и добавить их в List<Users>
. который в коде является List<Deelnemer>
Это выглядит следующим образом:
List<Deelnemer> tempDeeln = new List<Deelnemer>();
bool dupes = false;
foreach (DataRow rij in deeln.Rows) {
Deelnemer dln = new Deelnemer();
dln.Dln_Creatiedatum = DateTime.Now;
dln.Dln_Email = rij["Ler_Email"].ToString();
dln.Dln_Inst_ID = inst.Inst_ID;
dln.Dln_Naam = rij["Ler_Naam"].ToString();
dln.Dln_Username = rij["LerLog_Username"].ToString();
dln.Dln_Voornaam = rij["Ler_Voornaam"].ToString();
dln.Dln_Update = (DateTime)rij["Ler_Update"];
if (!dupes amp;amp; tempDeeln.Count(q => q.FullName.ToLower() == dln.FullName.ToLower()) > 0)
dupes = true;
tempDeeln.Add(dln);
}
затем, когда foreach выполнен, я смотрю, имеет ли значение bool значение true, проверяю, какие из них являются двойными, и удаляю самые старые.
теперь, я думаю, что эта часть кода очень плоха:
if (!dupes amp;amp; tempDeeln.Count(q => q.FullName.ToLower() == dln.FullName.ToLower()) > 0)
он выполняется для каждого добавленного пользователя и выполняется для всех уже созданных пользователей.
мой вопрос: как бы мне это оптимизировать.
Ответ №1:
Вы можете использовать набор, такой как HashSet<T>
для отслеживания уникальных имен, наблюдаемых до сих пор. Хэш-набор поддерживает вставку и поиск в постоянном времени, поэтому полный линейный поиск не потребуется для каждого нового элемента, в отличие от вашего существующего решения.
var uniqueNames = new HashSet<string>(StringComparer.CurrentCultureIgnoreCase);
...
foreach(...)
{
...
if(!dupes)
{
// Expression is true only if the set already contained the string.
dupes = !uniqueNames.Add(dln.FullName);
}
}
Если вы хотите «удалить» дубликаты (т. Е. создать по одному репрезентативному элементу для каждого имени), после того, как вы собрали список (без использования хэш-набора), вы можете сделать:
var distinctItems = tempDeeln.GroupBy(dln => dln.FullName,
StringComparer.CurrentCultureIgnoreCase)
.Select(g => g.First());
Комментарии:
1. Мне нравится решение HashSet, но я не вижу, как может работать решение «select distinct».
2. @Magnus: Ты прав; это было замораживанием мозга. Не уверен, о чем я думал. Спасибо, что указали на это.
Ответ №2:
Попробуйте это—
http://blogs.msdn.com/b/ericwhite/archive/2008/08/19/find-duplicates-using-linq.aspx
Ответ №3:
Подсчет будет проходить через весь набор элементов. Попробуйте использовать любой, таким образом, он будет проверять только первое вхождение элемента.
if (!dupes amp;amp; tempDeeln.Any(q => q.FullName.ToLower() == dln.FullName.ToLower()))
dupes = true;