#c# #linq #sharepoint-2007
#c# #linq #sharepoint-2007
Вопрос:
Мне нужно составить список пользователей с помощью пользовательского поиска, где я беру всех пользователей из всех групп, добавленных в список разрешений в sharepoint web. Моя проблема в том, что пользователи могут состоять в нескольких группах, поэтому они добавляются несколько раз в возвращаемый список. Как мне убедиться, что он добавляется только один раз?
C#
// keywords is the whatever value a user types into the search textbox
private static IEnumerable<SPUser> GetUsers(SPWeb web, string keywords)
{
var oList = new List<SPUser>();
var oListUsers = web.Groups.Cast<SPGroup>().SelectMany(grp => grp.Users.Cast<SPUser>().Where(user => user.Name.Contains(keywords))).ToList();
foreach (SPUser user in oListUsers)
{
// My attempt here is to check if the list already contains the current item
// but it seems to ignore it. I've tried counting too, but same outcome.
if (!oList.Contains(user))
oList.Add(user);
}
return oList;
}
Комментарии:
1. oList. Contains(user) возвращает false, даже если пользователь есть в этом списке?
2. .Contains() проверяет ссылку, является ли тип ссылочным типом, и возвращает false, если oList не содержит ссылки на тот же объект, на который ссылается текущая итерация user. Однако вы можете переопределить . Метод Equals() в классе для принудительного выполнения определенного сравнения (для пользователя. Свойство Name, например).
Ответ №1:
Попробуйте это (вместо contains)
if (! oList.Any(u => u.Name == user.Name ))
{
oList.Add(user);
}
Ответ №2:
Похоже, вашему классу SPUser необходимо реализовать IEquatable<SPUser>
, чтобы containes работал так, как вы этого хотите.
Ответ №3:
Вы можете использовать Linq для получения уникальных записей
var uniqueValues = oList.Distinct();
Это приведет к удалению SPUser
объекта с той же ссылкой. Также вы можете реализовать IEqualityCompaprer<SPUser>
для своей собственной логики равенства
Ответ №4:
Используйте Hashset вместо списка. Таким образом, вам не нужно проверять наличие содержимого, а повторяющиеся элементы будут просто игнорироваться.
Это тоже будет быстрее, поскольку HashSet способен отклонять дубликаты почти тривиально, в то время как List<>.Contains() равен O (n)
var oList = new HashSet<SPUser>();
var oListUsers = web.Groups.Cast<SPGroup>().SelectMany(grp => grp.Users.Cast<SPUser> ().Where(user => user.Name.Contains(keywords))).ToList();
foreach (SPUser user in oListUsers)
{
oList.Add(user);
}
Ответ №5:
Используя грубую силу, вы могли бы просто использовать Distinct:
var oListUsers = web.Groups.Cast<SPGroup>().SelectMany(grp => grp.Users.Cast<SPUser>().Where(user => user.Name.Contains(keywords))).Distinct().ToList();
Ответ №6:
Проблема в том, что в вашем oListUsers
списке есть разные объекты, которые представляют одного и того же пользователя, но имеют разные ссылки на объекты — поскольку Contains()
для проверки используются ссылки на объекты, вы не сможете отследить этот случай, если не определите пользовательский компаратор / равенство в вашем SPUser
классе.
В качестве альтернативы, если, например, имя пользователя уникально, вы могли бы отфильтровать дубликаты таким образом.