From 524ba0f7bafa206dcc1cbf571ec6dd61eb0b2e45 Mon Sep 17 00:00:00 2001 From: Vladimir Pecanac Date: Sun, 1 Nov 2026 13:29:46 +0100 Subject: [PATCH] Filter a list based on another list: .NET 10, RemoveAll, HashSet lookup, Join and IntersectBy demos --- ...lterAListBasedOnAnotherListInCSharp.csproj | 2 +- .../Program.cs | 18 +++++ .../School.cs | 2 +- .../Student.cs | 4 +- .../Utilities.cs | 27 +++++++ ...AListBasedOnAnotherListInCSharpUnitTest.cs | 72 ++++++++++++++++++- .../Tests/Tests.csproj | 10 +-- 7 files changed, 125 insertions(+), 10 deletions(-) diff --git a/collections-lists/HowToFilterAListBasedOnAnotherListInCSharp/HowToFilterAListBasedOnAnotherListInCSharp/HowToFilterAListBasedOnAnotherListInCSharp.csproj b/collections-lists/HowToFilterAListBasedOnAnotherListInCSharp/HowToFilterAListBasedOnAnotherListInCSharp/HowToFilterAListBasedOnAnotherListInCSharp.csproj index 2150e3797b..ed9781c223 100644 --- a/collections-lists/HowToFilterAListBasedOnAnotherListInCSharp/HowToFilterAListBasedOnAnotherListInCSharp/HowToFilterAListBasedOnAnotherListInCSharp.csproj +++ b/collections-lists/HowToFilterAListBasedOnAnotherListInCSharp/HowToFilterAListBasedOnAnotherListInCSharp/HowToFilterAListBasedOnAnotherListInCSharp.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net10.0 enable enable diff --git a/collections-lists/HowToFilterAListBasedOnAnotherListInCSharp/HowToFilterAListBasedOnAnotherListInCSharp/Program.cs b/collections-lists/HowToFilterAListBasedOnAnotherListInCSharp/HowToFilterAListBasedOnAnotherListInCSharp/Program.cs index 8fbaeb8b69..377455432e 100644 --- a/collections-lists/HowToFilterAListBasedOnAnotherListInCSharp/HowToFilterAListBasedOnAnotherListInCSharp/Program.cs +++ b/collections-lists/HowToFilterAListBasedOnAnotherListInCSharp/HowToFilterAListBasedOnAnotherListInCSharp/Program.cs @@ -26,6 +26,12 @@ Console.WriteLine(Utilities.PrintList(filteredContainedInts)); Console.WriteLine(); +Console.WriteLine("REMOVEALL"); +List intsToChange = [1, 2, 3, 4, 4, 4, 5, 6, 7, 7, 8, 8, 9]; +int removedCount = Utilities.RemoveNotContained(intsToChange, filteringIntList); +Console.WriteLine($"Removed {removedCount}, left: {Utilities.PrintList(intsToChange)}"); +Console.WriteLine(); + Console.WriteLine("DUPLICATES"); Console.WriteLine("Unique elements from list 1 that are contained in list 2:"); filteredContainedInts = Utilities.FilterContainedUnique(intsToFilter, filteringIntList); @@ -78,6 +84,13 @@ Console.WriteLine(Utilities.PrintList(filteredStudents)); Console.WriteLine(); +Console.WriteLine("INTERSECTBY"); +Console.WriteLine(Utilities.PrintList(Utilities.FilterStudentsBySchoolCityUsingIntersectBy(studentsToFilter, schoolsToFilter))); +Console.WriteLine(); +Console.WriteLine("JOIN"); +Console.WriteLine(Utilities.PrintList(Utilities.FilterStudentsBySchoolCityUsingJoin(studentsToFilter, schoolsToFilter))); +Console.WriteLine(); + Console.WriteLine("SPECIFIC PROPERTIES"); List schoolIds = [1, 3]; Console.WriteLine("Names of students from list 1 that attend schools with IDs from list 2:"); @@ -100,6 +113,11 @@ Console.WriteLine(Utilities.PrintList(filteredContainedInts)); Console.WriteLine(); +Console.WriteLine("HASHSET LOOKUP"); +Console.WriteLine(Utilities.PrintList(Utilities.FilterContainedUsingHashSetLookup(intsToFilter, filteringIntList))); +Console.WriteLine(Utilities.PrintList(Utilities.FilterContainedUsingHashSetLookup([1, 2, 3, 4, 4, 4, 5, 6, 7, 7, 8, 8, 9], [4, 4, 7, 9, 10]))); +Console.WriteLine(); + Console.WriteLine("MASKS"); intsToFilter = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; List mask = [true, false, false, false]; diff --git a/collections-lists/HowToFilterAListBasedOnAnotherListInCSharp/HowToFilterAListBasedOnAnotherListInCSharp/School.cs b/collections-lists/HowToFilterAListBasedOnAnotherListInCSharp/HowToFilterAListBasedOnAnotherListInCSharp/School.cs index cb2bee3c3e..1643498fc8 100644 --- a/collections-lists/HowToFilterAListBasedOnAnotherListInCSharp/HowToFilterAListBasedOnAnotherListInCSharp/School.cs +++ b/collections-lists/HowToFilterAListBasedOnAnotherListInCSharp/HowToFilterAListBasedOnAnotherListInCSharp/School.cs @@ -3,5 +3,5 @@ public class School { public int Id { get; set; } - public string City { get; set; } + public string City { get; set; } = string.Empty; } diff --git a/collections-lists/HowToFilterAListBasedOnAnotherListInCSharp/HowToFilterAListBasedOnAnotherListInCSharp/Student.cs b/collections-lists/HowToFilterAListBasedOnAnotherListInCSharp/HowToFilterAListBasedOnAnotherListInCSharp/Student.cs index f708ebf85a..0d15ce2659 100644 --- a/collections-lists/HowToFilterAListBasedOnAnotherListInCSharp/HowToFilterAListBasedOnAnotherListInCSharp/Student.cs +++ b/collections-lists/HowToFilterAListBasedOnAnotherListInCSharp/HowToFilterAListBasedOnAnotherListInCSharp/Student.cs @@ -3,9 +3,9 @@ public class Student { public int Id { get; set; } - public string Name { get; set; } + public string Name { get; set; } = string.Empty; public int SchoolId { get; set; } - public string City { get; set; } + public string City { get; set; } = string.Empty; override public string ToString() { diff --git a/collections-lists/HowToFilterAListBasedOnAnotherListInCSharp/HowToFilterAListBasedOnAnotherListInCSharp/Utilities.cs b/collections-lists/HowToFilterAListBasedOnAnotherListInCSharp/HowToFilterAListBasedOnAnotherListInCSharp/Utilities.cs index 22f7916fc8..00c9bc029f 100644 --- a/collections-lists/HowToFilterAListBasedOnAnotherListInCSharp/HowToFilterAListBasedOnAnotherListInCSharp/Utilities.cs +++ b/collections-lists/HowToFilterAListBasedOnAnotherListInCSharp/HowToFilterAListBasedOnAnotherListInCSharp/Utilities.cs @@ -97,4 +97,31 @@ public static List FilterUsingMask(List listToFilter, List mask) { return listToFilter.Where((item, index) => mask[index % mask.Count]).ToList(); } + + public static int RemoveNotContained(List listToFilter, List filteringList) + { + return listToFilter.RemoveAll(item => !filteringList.Contains(item)); + } + + public static List FilterContainedUsingHashSetLookup(List listToFilter, List filteringList) + { + HashSet lookup = filteringList.ToHashSet(); + + return listToFilter.Where(lookup.Contains).ToList(); + } + + public static List FilterStudentsBySchoolCityUsingIntersectBy(List listToFilter, List filteringList) + { + return listToFilter.IntersectBy(filteringList.Select(school => school.City), student => student.City) + .ToList(); + } + + public static List FilterStudentsBySchoolCityUsingJoin(List listToFilter, List filteringList) + { + return listToFilter.Join(filteringList, + student => student.City, + school => school.City, + (student, school) => student) + .ToList(); + } } diff --git a/collections-lists/HowToFilterAListBasedOnAnotherListInCSharp/Tests/HowToFilterAListBasedOnAnotherListInCSharpUnitTest.cs b/collections-lists/HowToFilterAListBasedOnAnotherListInCSharp/Tests/HowToFilterAListBasedOnAnotherListInCSharpUnitTest.cs index 413b7ff333..6f59860a5b 100644 --- a/collections-lists/HowToFilterAListBasedOnAnotherListInCSharp/Tests/HowToFilterAListBasedOnAnotherListInCSharpUnitTest.cs +++ b/collections-lists/HowToFilterAListBasedOnAnotherListInCSharp/Tests/HowToFilterAListBasedOnAnotherListInCSharpUnitTest.cs @@ -231,4 +231,74 @@ public void Given2Lists_WhenFilterUsingMaskMethodCalled_ThenOnlyElementsCorrespo // Assert Assert.Equal([50, 7], output); } -} \ No newline at end of file + + [Fact] + public void Given2Lists_WhenRemoveNotContainedMethodCalled_ThenListIsChangedInPlace() + { + // Arrange + List numbers = [17, 34, 50, 68, 121, 7, 145]; + List otherNumbers = [50, 44, 121]; + + // Act + var removed = Utilities.RemoveNotContained(numbers, otherNumbers); + + // Assert + Assert.Equal(5, removed); + Assert.Equal([50, 121], numbers); + } + + [Fact] + public void Given2Lists_WhenFilterContainedUsingHashSetLookupMethodCalled_ThenOrderAndDuplicatesAreKept() + { + // Arrange + List numbers = [121, 17, 50, 50, 68, 121, 7]; + List otherNumbers = [50, 44, 121]; + + // Act + var output = Utilities.FilterContainedUsingHashSetLookup(numbers, otherNumbers); + + // Assert + Assert.Equal([121, 50, 50, 121], output); + } + + [Fact] + public void Given2Lists_WhenFilterStudentsBySchoolCityUsingIntersectByMethodCalled_ThenOneStudentPerCityIsKept() + { + // Arrange + List students = + [ + new Student { Id = 1, Name = "Alice", SchoolId = 1, City = "Paris" }, + new Student { Id = 2, Name = "Bob", SchoolId = 2, City = "Reims" }, + new Student { Id = 5, Name = "Eve", SchoolId = 2, City = "Reims" } + ]; + List schools = [new School { Id = 1, City = "Paris" }, new School { Id = 2, City = "Reims" }]; + + // Act + var output = Utilities.FilterStudentsBySchoolCityUsingIntersectBy(students, schools) + .Select(student => student.Name).ToList(); + + // Assert + Assert.Equal(["Alice", "Bob"], output); + } + + [Fact] + public void Given2Lists_WhenFilterStudentsBySchoolCityUsingJoinMethodCalled_ThenEveryMatchingStudentIsKept() + { + // Arrange + List students = + [ + new Student { Id = 1, Name = "Alice", SchoolId = 1, City = "Paris" }, + new Student { Id = 2, Name = "Bob", SchoolId = 2, City = "Reims" }, + new Student { Id = 3, Name = "Charlie", SchoolId = 1, City = "Calais" }, + new Student { Id = 5, Name = "Eve", SchoolId = 2, City = "Reims" } + ]; + List schools = [new School { Id = 1, City = "Paris" }, new School { Id = 2, City = "Reims" }]; + + // Act + var output = Utilities.FilterStudentsBySchoolCityUsingJoin(students, schools) + .Select(student => student.Name).ToList(); + + // Assert + Assert.Equal(["Alice", "Bob", "Eve"], output); + } +} diff --git a/collections-lists/HowToFilterAListBasedOnAnotherListInCSharp/Tests/Tests.csproj b/collections-lists/HowToFilterAListBasedOnAnotherListInCSharp/Tests/Tests.csproj index 125cc0c22b..8857323730 100644 --- a/collections-lists/HowToFilterAListBasedOnAnotherListInCSharp/Tests/Tests.csproj +++ b/collections-lists/HowToFilterAListBasedOnAnotherListInCSharp/Tests/Tests.csproj @@ -1,7 +1,7 @@ - net8.0 + net10.0 enable enable @@ -10,13 +10,13 @@ - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all