How to filter a list?
Th开发者_Go百科is is a method that should take already assigned users out of a list and keep non-assigned ones in a list. The GuidList has the userId added to it on a button click. The profileList is used to populate a gridView.
Here is the code:
private VList<VW_profiles> FilterAssigned(VList<VW_profiles> profileList)
{
VList<VW_profiles> sortedList = new VList<VW_profiles>();
foreach(VW_profiles profile in profileList)
{
if(GuidList.Count > 0)
{
foreach(Guid userId in GuidList)
{
if(profile.UserId != userId)
{
sortedList.Add(profile)
}
}
}
else
{
sortedList = profileList;
}
}
return sortedList;
}
Now here's my problem. Everythings seems to work well up until all of the items in the profileList have also been added to the GuidList. Then instead of doing a negate on the two Guid ID's, we start adding everyone in again. Does anyone have any suggestions on how to do this is a more effecient way and to avoid the adding in once we've taken everything out.
Thanks!
If VList<T>
is a List<T>
, then you can do this:
profileList.RemoveAll(profile => GuidList.Contains(profile.UserId));
If performance is an issue and there are LOTS of Guids to remove, then you can make GuidList a HashSet<Guid>
.
Edit Based on comments: If you don't want to modify the original list, then do this:
var filtered = new VList<VW_profiles>(
profileList.Where(profile => !GuidList.Contains(profile.UserId)));
Edit If you are not using a List<T>
, here is a method you can use on resizable lists implementing IList<T>
and one you can use on arrays (T[]
). By only ever removing items from the end of the list, what would be an O(n²) algorithm will be O(n) for most implementations of IList<T>
.
public static void RemoveAll<T>(this IList<T> list, Predicate<T> match)
{
if (list == null)
throw new ArgumentNullException("list");
if (match == null)
throw new ArgumentNullException("match");
if (list is T[])
throw new ArgumentException("Arrays cannot be resized.");
// early out
if (list.Count == 0)
return;
// List<T> provides special handling
List<T> genericList = list as List<T>;
if (genericList != null)
{
genericList.RemoveAll(match);
return;
}
int targetIndex = 0;
for (int i = 0; i < list.Count; i++)
{
if (!match(list[i]) && targetIndex != i)
{
list[targetIndex] = list[i];
targetIndex++;
}
}
// Unfortunately IList<T> doesn't have RemoveRange either
for (int i = list.Count - 1; i >= targetIndex; i--)
{
list.RemoveAt(i);
}
}
public static void RemoveAll<T>(ref T[] array, Predicate<T> match)
{
if (array == null)
throw new ArgumentNullException("array");
if (match == null)
throw new ArgumentNullException("match");
int targetIndex = 0;
for (int i = 0; i < array.Length; i++)
{
if (!match(array[i]) && targetIndex != i)
{
array[targetIndex] = array[i];
targetIndex++;
}
}
if (targetIndex != array.Length)
{
Array.Resize(ref array, targetIndex);
}
}
Your problem is in this code:
foreach(Guid userId in GuidList)
{
if(profile.UserId != userId)
{
sortedList.Add(profile)
}
}
It should be more like:
bool inList = false;
foreach(Guid userId in GuidList)
{
if(profile.UserId == userId)
{
inList = true;
}
}
if (!inList)
sortedList.Add(profile)
or, the more LINQ-style:
bool inList = GuidList.Any(x => x == profile.UserId);
if (!inList)
sortedList.Add(profile)
your current code is more like:
GuidList.Where(x => x != profile.UserId)
.Foreach(x => sortedList.Add(x));
which I'm thinking isn't what you want :)
精彩评论