├── .gitignore ├── Exercises ├── Aggregate.cs ├── All.cs ├── Any.cs ├── Average.cs ├── CollectionTypeChange.cs ├── ConcatUnion.cs ├── Contains.cs ├── Count.cs ├── Distinct.cs ├── ElementAt.cs ├── Exercises.csproj ├── FirstLast.cs ├── GeneratingNewCollection.cs ├── GroupByQuerySyntax.cs ├── Grouping.cs ├── IntersectExcept.cs ├── Join.cs ├── JoinQuerySyntax.cs ├── MinMax.cs ├── OfType.cs ├── OrderBy.cs ├── OrderByQuerySyntax.cs ├── PrependAppend.cs ├── Select.cs ├── SelectMany.cs ├── SelectManyQuerySyntax.cs ├── SelectQuerySyntax.cs ├── Single.cs ├── Skip.cs ├── Sum.cs ├── Take.cs ├── Where.cs ├── WhereQuerySyntax.cs └── Zip.cs ├── ExercisesSolutions ├── Aggregate.cs ├── All.cs ├── Any.cs ├── Average.cs ├── CollectionTypeChange.cs ├── ConcatUnion.cs ├── Contains.cs ├── Count.cs ├── Distinct.cs ├── ElementAt.cs ├── ExercisesSolutions.csproj ├── FirstLast.cs ├── GeneratingNewCollection.cs ├── GroupByQuerySyntax.cs ├── Grouping.cs ├── IntersectExcept.cs ├── Join.cs ├── JoinQuerySyntax.cs ├── MinMax.cs ├── OfType.cs ├── OrderBy.cs ├── OrderByQuerySyntax.cs ├── PrependAppend.cs ├── Select.cs ├── SelectMany.cs ├── SelectManyQuerySyntax.cs ├── SelectQuerySyntax.cs ├── Single.cs ├── Skip.cs ├── Sum.cs ├── Take.cs ├── Where.cs ├── WhereQuerySyntax.cs └── Zip.cs ├── ExercisesTests ├── Aggregate_Exercise1_Tests.cs ├── Aggregate_Exercise2_Tests.cs ├── Aggregate_RefactoringChallenge_Tests.cs ├── All_Exercise1_Tests.cs ├── All_Exercise2_Tests.cs ├── All_RefactoringChallenge_Tests.cs ├── Any_Exercise1_Tests.cs ├── Any_Exercise2_Tests.cs ├── Any_RefactoringChallenge_Tests.cs ├── Average_Exercise1_Tests.cs ├── Average_Exercise2_Tests.cs ├── Average_RefactoringChallenge_Tests.cs ├── CollectionTypeChange_Exercise1_Tests.cs ├── CollectionTypeChange_Exercise2_Tests.cs ├── CollectionTypeChange_RefactoringChallenge_Tests.cs ├── ConcatUnion_Exercise1_Tests.cs ├── ConcatUnion_Exercise2_Tests.cs ├── ConcatUnion_RefactoringChallenge_Tests.cs ├── Contains_Exercise1_Tests.cs ├── Contains_Exercise2_Tests.cs ├── Contains_RefactoringChallenge_Tests.cs ├── Count_Exercise1_Tests.cs ├── Count_Exercise2_Tests.cs ├── Count_RefactoringChallenge_Tests.cs ├── Distinct_Exercise1_Tests.cs ├── Distinct_Exercise2_Tests.cs ├── Distinct_RefactoringChallenge_Tests.cs ├── ElementAt_Exercise1_Tests.cs ├── ElementAt_Exercise2_Tests.cs ├── ElementAt_RefactoringChallenge_Tests.cs ├── ExercisesTests.csproj ├── FirstLast_Exercise1_Tests.cs ├── FirstLast_Exercise2_Tests.cs ├── FirstLast_RefactoringChallenge_Tests.cs ├── GeneratingNewCollection_Exercise1_Tests.cs ├── GeneratingNewCollection_Exercise2_Tests.cs ├── GeneratingNewCollection_RefactoringChallenge_Tests.cs ├── GroupBy_QuerySyntax_Exercise1_Tests.cs ├── GroupBy_QuerySyntax_Exercise2_Tests.cs ├── GroupBy_QuerySyntax_RefactoringChallenge_Tests.cs ├── Grouping_Exercise1_Tests.cs ├── Grouping_Exercise2_Tests.cs ├── Grouping_RefactoringChallenge_Tests.cs ├── IntersectExcept_Exercise1_Tests.cs ├── IntersectExcept_Exercise2_Tests.cs ├── IntersectExcept_RefactoringChallenge_Tests.cs ├── Join_Exercise1_Tests.cs ├── Join_Exercise2_Tests.cs ├── Join_QuerySyntax_Exercise1_Tests.cs ├── Join_QuerySyntax_Exercise2_Tests.cs ├── Join_QuerySyntax_RefactoringChallenge_Tests.cs ├── Join_RefactoringChallenge_Tests.cs ├── MinMax_Exercise1_Tests.cs ├── MinMax_Exercise2_Tests.cs ├── MinMax_RefactoringChallenge_Tests.cs ├── OfType_Exercise1_Tests.cs ├── OfType_Exercise2_Tests.cs ├── OfType_RefactoringChallenge_Tests.cs ├── OrderBy_Exercise1_Tests.cs ├── OrderBy_Exercise2_Tests.cs ├── OrderBy_QuerySyntax_Exercise1_Tests.cs ├── OrderBy_QuerySyntax_Exercise2_Tests.cs ├── OrderBy_QuerySyntax_RefactoringChallenge_Tests.cs ├── OrderBy_RefactoringChallenge_Tests.cs ├── PrependAppend_Exercise1_Tests.cs ├── PrependAppend_Exercise2_Tests.cs ├── PrependAppend_RefactoringChallenge_Tests.cs ├── SelectMany_Exercise1_Tests.cs ├── SelectMany_Exercise2_Tests.cs ├── SelectMany_QuerySyntax_Exercise1_Tests.cs ├── SelectMany_QuerySyntax_Exercise2_Tests.cs ├── SelectMany_QuerySyntax_RefactoringChallenge_Tests.cs ├── SelectMany_RefactoringChallenge_Tests.cs ├── SelectQuerySyntax_Exercise1_Tests.cs ├── SelectQuerySyntax_Exercise2_Tests.cs ├── SelectQuerySyntax_RefactoringChalenge_Tests.cs ├── Select_Exercise1_Tests.cs ├── Select_Exercise2_Tests.cs ├── Select_QuerySyntax_Exercise1_Tests.cs ├── Select_QuerySyntax_Exercise2_Tests.cs ├── Select_QuerySyntax_RefactoringChallenge_Tests.cs ├── Select_RefactoringChallenge_Tests.cs ├── Single_Exercise1_Tests.cs ├── Single_Exercise2_Tests.cs ├── Single_RefactoringChallenge_Tests.cs ├── Skip_Exercise1_Tests.cs ├── Skip_Exercise2_Tests.cs ├── Skip_RefactoringChallenge_Tests.cs ├── Sum_Exercise1_Tests.cs ├── Sum_Exercise2_Tests.cs ├── Sum_RefactoringChallenge_Tests.cs ├── Take_Exercise1_Tests.cs ├── Take_Exercise2_Tests.cs ├── Take_RefactoringChallenge_Tests.cs ├── Utilities │ └── TestUtilities.cs ├── Where_Exercise1_Tests.cs ├── Where_Exercise2_Tests.cs ├── Where_QuerySyntax_Exercise1_Tests.cs ├── Where_QuerySyntax_Exercise2_Tests.cs ├── Where_QuerySyntax_RefactoringChallenge_Tests.cs ├── Where_RefactoringChallenge_Tests.cs ├── Zip_Exercise1_Tests.cs ├── Zip_Exercise2_Tests.cs └── Zip_RefactoringChallenge_Tests.cs ├── LinqTutorial.sln ├── LinqTutorial ├── Data │ └── Data.cs ├── DataTypes │ ├── Pet.cs │ ├── PetEqualityByIdComparer.cs │ ├── PetOwner.cs │ ├── PetType.cs │ ├── VeterinaryClinic.cs │ └── VeterinaryClinicAppointment.cs ├── Examples │ ├── Aggregate.cs │ ├── All.cs │ ├── Any.cs │ ├── Average.cs │ ├── ConcatUnion.cs │ ├── Contains.cs │ ├── Count.cs │ ├── Distinct.cs │ ├── DotNet6Improvements.cs │ ├── DotNet9Improvements.cs │ ├── ElementAt.cs │ ├── FirstLast.cs │ ├── GeneratingNewCollection.cs │ ├── GroupBy.cs │ ├── GroupJoin.cs │ ├── IntersectExcept.cs │ ├── Joins.cs │ ├── MinMax.cs │ ├── OfType.cs │ ├── OrderBy.cs │ ├── PrependAppend.cs │ ├── Select.cs │ ├── SelectMany.cs │ ├── SingleElement.cs │ ├── Skip.cs │ ├── Sum.cs │ ├── Take.cs │ ├── TypeSwitching.cs │ ├── Where.cs │ └── Zip.cs ├── LinqTutorial.csproj └── Program.cs ├── README.md └── Utilities ├── Printer.cs └── Utilities.csproj /.gitignore: -------------------------------------------------------------------------------- 1 | [Oo]bj 2 | [Bb]in 3 | *.user 4 | *.suo 5 | *.[Cc]ache 6 | *.bak 7 | *.ncb 8 | *.log 9 | *.v2 10 | .vs 11 | *.DS_Store 12 | [Tt]humbs.db 13 | _ReSharper.* 14 | *.resharper 15 | Ankh.NoLoad -------------------------------------------------------------------------------- /Exercises/All.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace Exercises 6 | { 7 | public static class All 8 | { 9 | //Coding Exercise 1 10 | //Use LINQ to implement the AreAllNumbersDivisibleBy10 method, 11 | //which checks if all numbers in the collection are divisible by 10. 12 | public static bool AreAllNumbersDivisibleBy10(int[] numbers) 13 | { 14 | //TODO your code goes here 15 | throw new NotImplementedException(); 16 | } 17 | 18 | //Coding Exercise 2 19 | //Using LINQ, implement the AreAllPetsOfTheSameType method that checks 20 | //if all Pets in the collection are of the same PetType. 21 | public static bool AreAllPetsOfTheSameType(IEnumerable pets) 22 | { 23 | //TODO your code goes here 24 | throw new NotImplementedException(); 25 | } 26 | 27 | //Refactoring challenge 28 | //TODO implement this method 29 | public static bool AreAllWordsOfTheSameLength_Refactored(List words) 30 | { 31 | //TODO your code goes here 32 | throw new NotImplementedException(); 33 | } 34 | 35 | //do not modify this method 36 | public static bool AreAllWordsOfTheSameLength(List words) 37 | { 38 | if (words.Count == 0 || words.Count == 1) 39 | { 40 | return true; 41 | } 42 | var length0 = words[0].Length; 43 | for (int i = 1; i < words.Count; ++i) 44 | { 45 | if (words[i].Length != length0) 46 | { 47 | return false; 48 | } 49 | } 50 | return true; 51 | } 52 | 53 | public enum PetType 54 | { 55 | Cat, 56 | Dog, 57 | Fish 58 | } 59 | 60 | public class Pet 61 | { 62 | public int Id { get; } 63 | public string Name { get; } 64 | public PetType PetType { get; } 65 | public float Weight { get; } 66 | 67 | public Pet(int id, string name, PetType petType, float weight) 68 | { 69 | Id = id; 70 | Name = name; 71 | PetType = petType; 72 | Weight = weight; 73 | } 74 | 75 | public override string ToString() 76 | { 77 | return $"Id: {Id}, Name: {Name}, Type: {PetType}, Weight: {Weight}"; 78 | } 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /Exercises/Any.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace Exercises 6 | { 7 | public class Any 8 | { 9 | //Coding Exercise 1 10 | //Using LINQ, implement the IsAnyNumberNegative method that checks 11 | //if any number in the collection is smaller than 0. 12 | public static bool IsAnyNumberNegative(IEnumerable numbers) 13 | { 14 | //TODO you code goes here 15 | throw new NotImplementedException(); 16 | } 17 | 18 | //Coding Exercise 2 19 | //Using LINQ, implement the AreThereAnyBigCats method, which will check 20 | //if in the collection of Pets there is a cat that weighs over 2 kilos. 21 | public static bool AreThereAnyBigCats(IEnumerable pets) 22 | { 23 | //TODO you code goes here 24 | throw new NotImplementedException(); 25 | } 26 | 27 | //Refactoring challenge 28 | //TODO implement this method 29 | public static bool AreAllNamesValid_Refactored(string[] names) 30 | { 31 | //TODO your code goes here 32 | throw new NotImplementedException(); 33 | } 34 | 35 | //do not modify this method 36 | public static bool AreAllNamesValid(string[] names) 37 | { 38 | foreach (var name in names) 39 | { 40 | if (char.IsLower(name[0])) 41 | { 42 | return false; 43 | } 44 | if (name.Length < 2) 45 | { 46 | return false; 47 | } 48 | if (name.Length > 25) 49 | { 50 | return false; 51 | } 52 | } 53 | return true; 54 | } 55 | 56 | public enum PetType 57 | { 58 | Cat, 59 | Dog, 60 | Fish 61 | } 62 | 63 | public class Pet 64 | { 65 | public int Id { get; } 66 | public string Name { get; } 67 | public PetType PetType { get; } 68 | public float Weight { get; } 69 | 70 | public Pet(int id, string name, PetType petType, float weight) 71 | { 72 | Id = id; 73 | Name = name; 74 | PetType = petType; 75 | Weight = weight; 76 | } 77 | 78 | public override string ToString() 79 | { 80 | return $"Id: {Id}, Name: {Name}, Type: {PetType}, Weight: {Weight}"; 81 | } 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /Exercises/Count.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace Exercises 6 | { 7 | public static class Count 8 | { 9 | //Coding Exercise 1 10 | //Implement the CountAllLongWords method, 11 | //which will count all words longer than 10 letters. 12 | public static int CountAllLongWords(IEnumerable words) 13 | { 14 | //TODO your code goes here 15 | throw new NotImplementedException(); 16 | } 17 | 18 | //Coding Exercise 2 19 | /* 20 | Using LINQ, implement the AreThereFewerOddThanEvenNumbers method, 21 | which will check if in the collection of numbers 22 | there are fewer odd than even numbers. 23 | For example: 24 | {2,3,4,5,6} -> will return true, because there are 3 even numbers (2,4,6) and 2 odd numbers (3,5) 25 | {3,4,5} ->  will return false, because there is 1 even number (4) and 2 odd numbers (3,5) 26 | {2,3,4,5} ->  will return false, because there are 2 even numbers (2,4) and 2 odd numbers (3,5) 27 | Remember, you can check if the number is even by using the modulo operation: 28 | number % 2 == 0 means the number is even 29 | number % 2 != 0 means the number is odd 30 | */ 31 | public static bool AreThereFewerOddThanEvenNumbers(IEnumerable numbers) 32 | { 33 | //TODO your code goes here 34 | throw new NotImplementedException(); 35 | } 36 | 37 | //Refactoring challenge 38 | //TODO implement this method 39 | public static bool IsAnySequenceTooLong_Refactored(IEnumerable> numberSequences, int maxLength) 40 | { 41 | //TODO your code goes here 42 | throw new NotImplementedException(); 43 | } 44 | 45 | //do not modify this method 46 | public static bool IsAnySequenceTooLong(IEnumerable> numberSequences, int maxLength) 47 | { 48 | foreach (var numberSequence in numberSequences) 49 | { 50 | var count = 0; 51 | foreach (var number in numberSequence) 52 | { 53 | ++count; 54 | } 55 | if (count > maxLength) 56 | { 57 | return true; 58 | } 59 | } 60 | return false; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Exercises/Exercises.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net9.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Exercises/OfType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Exercises 5 | { 6 | public static class OfType 7 | { 8 | //Coding Exercise 1 9 | //Implement the GetTheFirstInteger method, which given a collection of objects, 10 | //will return the first integer from this collection. 11 | //If no integer is present, it shall return null. 12 | public static int? GetTheFirstInteger(IEnumerable objects) 13 | { 14 | //TODO your code goes here 15 | throw new NotImplementedException(); 16 | } 17 | 18 | //Coding Exercise 2 19 | //Implement the AreAllStringsUpperCase method which will check if all strings 20 | //present in the objects collection are upper case. 21 | //If there is no string at all in this collection, the result should be true. 22 | public static bool AreAllStringsUpperCase(IEnumerable objects) 23 | { 24 | //TODO your code goes here 25 | throw new NotImplementedException(); 26 | } 27 | 28 | //Refactoring challenge 29 | //TODO implement this method 30 | public static DateTime? GetTheLatestDate_Refactored(IEnumerable objects) 31 | { 32 | //TODO your code goes here 33 | throw new NotImplementedException(); 34 | } 35 | 36 | //do not modify this method 37 | public static DateTime? GetTheLatestDate(IEnumerable objects) 38 | { 39 | DateTime? lastDate = null; 40 | foreach (var obj in objects) 41 | { 42 | var dateTime = obj as DateTime?; 43 | if (dateTime != null) 44 | { 45 | if (lastDate == null || lastDate < dateTime) 46 | { 47 | lastDate = dateTime; 48 | } 49 | } 50 | } 51 | return lastDate; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Exercises/OrderBy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace Exercises 6 | { 7 | public static class OrderBy 8 | { 9 | //Coding Exercise 1 10 | /* 11 | Using LINQ, implement the OrderFromLongestToShortest method, which takes 12 | a collection of strings, and returns those strings ordered from 13 | longest to shortest. 14 | For example, for {"bb", "a", "ccc"} the result should be {"ccc", "bb", "a"} 15 | */ 16 | public static IEnumerable OrderFromLongestToShortest( 17 | IEnumerable words) 18 | { 19 | //TODO your code goes here 20 | throw new NotImplementedException(); 21 | } 22 | 23 | //Coding Exercise 2 24 | /* 25 | Using LINQ, implement the FirstEvenThenOddDescending method, 26 | which orders numbers like this: 27 | *first, the even numbers 28 | *then, the odd numbers 29 | Then the numbers should be ordered descending. 30 | For example, for numbers {1,2,3,4,5,6,7} the result should be: {6,4,2,7,5,3,1}. 31 | */ 32 | public static IEnumerable FirstEvenThenOddDescending( 33 | IEnumerable numbers) 34 | { 35 | //TODO your code goes here 36 | throw new NotImplementedException(); 37 | } 38 | 39 | //Refactoring challenge 40 | //TODO implement this method 41 | public static IEnumerable OrderByMonth_Refactored(List dates) 42 | { 43 | //TODO your code goes here 44 | throw new NotImplementedException(); 45 | } 46 | 47 | //do not modify this method 48 | public static IEnumerable OrderByMonth(List dates) 49 | { 50 | dates.Sort((left, right) => 51 | { 52 | return left.Month.CompareTo(right.Month); 53 | }); 54 | return dates; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Exercises/Sum.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace Exercises 6 | { 7 | public static class Sum 8 | { 9 | //Coding Exercise 1 10 | /* 11 | Implement the TotalLength method, which given a collection of words will 12 | calculate the sum of their lengths. 13 | For example, for words {"little", "brown", "fox"} the result shall be 14 | 14 because the lengths of those words are 6, 5, and 3, which sums up to 14. 15 | Assume the result is not null. 16 | */ 17 | public static int TotalLength(IEnumerable words) 18 | { 19 | //TODO your code goes here 20 | throw new NotImplementedException(); 21 | } 22 | 23 | //Coding Exercise 2 24 | /* 25 | Implement the AverageSum method, which given a nested collection of numbers 26 | (so a collection of collections of numbers) will return the average sum 27 | for those collections. 28 | For example, for the following input... 29 | { 30 |     {1,2,3,2}, //sum is 8 31 |     {1,5,6}, //sum is 12 32 |     {2,2} //sum is 4 33 | } 34 | ...the result shall be 8 because the average sum is (8+12+4)/3 = 8. 35 | 36 | Assume the result is not null and non-empty. 37 | */ 38 | public static double AverageSum( 39 | IEnumerable> collectionsOfNumbers) 40 | { 41 | //TODO your code goes here 42 | throw new NotImplementedException(); 43 | } 44 | 45 | //Refactoring challenge 46 | //TODO implement this method 47 | public static bool HasAnyStudentSumOfMarksLargerThan100_Refactored( 48 | IEnumerable students) 49 | { 50 | //TODO your code goes here 51 | throw new NotImplementedException(); 52 | } 53 | 54 | //do not modify this method 55 | public static bool HasAnyStudentSumOfMarksLargerThan100( 56 | IEnumerable students) 57 | { 58 | foreach (var student in students) 59 | { 60 | var sumOfMarks = 0; 61 | foreach (var mark in student.Marks) 62 | { 63 | sumOfMarks += mark; 64 | } 65 | if (sumOfMarks > 100) 66 | { 67 | return true; 68 | } 69 | } 70 | return false; 71 | } 72 | 73 | public class Student 74 | { 75 | public IEnumerable Marks { get; set; } 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /ExercisesSolutions/Aggregate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace ExercisesSolutions 6 | { 7 | public static class Aggregate 8 | { 9 | //Coding Exercise 1 10 | public static TimeSpan TotalActivityDuration( 11 | IEnumerable activityTimesInSeconds) 12 | { 13 | return activityTimesInSeconds 14 | .Aggregate( 15 | new TimeSpan(), 16 | (totalTimeSpan, activitySeconds) => 17 | totalTimeSpan.Add( 18 | TimeSpan.FromSeconds(activitySeconds))); 19 | } 20 | 21 | //Coding Exercise 2 22 | public static string PrintAlphabet(int count) 23 | { 24 | if (count < 1 || count > 26) 25 | { 26 | throw new ArgumentException($"'{nameof(count)}' must be between 1 and 26"); 27 | } 28 | return Enumerable.Range(1, count - 1) 29 | .Aggregate("a", (accumulated, index) => $"{accumulated},{(char)('a' + index)}"); 30 | } 31 | 32 | //Refactoring challenge 33 | public static IEnumerable Fibonacci_Refactored(int n) 34 | { 35 | if (n < 1) 36 | { 37 | throw new ArgumentException( 38 | $"Can't generate Fibonacci sequence " + 39 | $"for {n} elements. N must be a " + 40 | $"positive number"); 41 | } 42 | 43 | if (n == 1) 44 | { 45 | return new[] { 0 }; 46 | } 47 | return Enumerable.Range(1, n - 2) 48 | .Aggregate( 49 | new List { 0, 1 } as IEnumerable, 50 | (sequence, nextIndex) => sequence.Append( 51 | sequence.ElementAt(nextIndex - 1) + 52 | sequence.ElementAt(nextIndex))); 53 | } 54 | 55 | //do not modify this method 56 | public static IEnumerable Fibonacci(int n) 57 | { 58 | if (n < 1) 59 | { 60 | throw new ArgumentException( 61 | $"Can't generate Fibonacci sequence " + 62 | $"for {n} elements. N must be a " + 63 | $"positive number"); 64 | } 65 | 66 | if (n == 1) 67 | { 68 | return new[] { 0 }; 69 | } 70 | var result = new List { 0, 1 }; 71 | for (int i = 1; i < n - 1; ++i) 72 | { 73 | result.Add(result[i - 1] + result[i]); 74 | } 75 | return result; 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /ExercisesSolutions/All.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace ExercisesSolutions 6 | { 7 | public static class All 8 | { 9 | //Coding Exercise 1 10 | public static bool AreAllNumbersDivisibleBy10(int[] numbers) 11 | { 12 | return numbers.All(n => n % 10 == 0); 13 | } 14 | 15 | //Coding Exercise 2 16 | public static bool AreAllPetsOfTheSameType(IEnumerable pets) 17 | { 18 | return 19 | pets.All(pet => pet.PetType == PetType.Dog) || 20 | pets.All(pet => pet.PetType == PetType.Cat) || 21 | pets.All(pet => pet.PetType == PetType.Fish); 22 | } 23 | 24 | //Refactoring challenge 25 | public static bool AreAllPetsOfTheSameType_AlternativeImplementation( 26 | IEnumerable pets) 27 | { 28 | var allPetTypes = Enum.GetValues(typeof(PetType)).Cast(); 29 | return allPetTypes.Any(petType => pets.All(pet => pet.PetType == petType)); 30 | } 31 | 32 | public static bool 33 | AreAllWordsOfTheSameLength_Refactored( 34 | List words) 35 | { 36 | return !words.Any() || 37 | words.All(word => 38 | word.Length == words[0].Length); 39 | } 40 | 41 | public static bool AreAllWordsOfTheSameLength( 42 | List words) 43 | { 44 | if (words.Count == 0 || words.Count == 1) 45 | { 46 | return true; 47 | } 48 | var length0 = words[0].Length; 49 | for (int i = 1; i < words.Count; ++i) 50 | { 51 | if (words[i].Length != length0) 52 | { 53 | return false; 54 | } 55 | } 56 | return true; 57 | } 58 | 59 | public enum PetType 60 | { 61 | Cat, 62 | Dog, 63 | Fish 64 | } 65 | 66 | public class Pet 67 | { 68 | public int Id { get; } 69 | public string Name { get; } 70 | public PetType PetType { get; } 71 | public float Weight { get; } 72 | 73 | public Pet(int id, string name, PetType petType, float weight) 74 | { 75 | Id = id; 76 | Name = name; 77 | PetType = petType; 78 | Weight = weight; 79 | } 80 | 81 | public override string ToString() 82 | { 83 | return $"Id: {Id}, Name: {Name}, Type: {PetType}, Weight: {Weight}"; 84 | } 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /ExercisesSolutions/Any.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace ExercisesSolutions 5 | { 6 | public static class Any 7 | { 8 | //Coding Exercise 1 9 | public static bool IsAnyNumberNegative(IEnumerable numbers) 10 | { 11 | return numbers.Any(number => number < 0); 12 | } 13 | 14 | //Coding Exercise 2 15 | public static bool AreThereAnyBigCats(IEnumerable pets) 16 | { 17 | return pets.Any(pet => pet.PetType == PetType.Cat && pet.Weight > 2); 18 | } 19 | 20 | //Refactoring challenge 21 | public static bool AreAllNamesValid_Refactored(string[] names) 22 | { 23 | return !names.Any(name => 24 | char.IsLower(name[0]) || 25 | name.Length < 2 || 26 | name.Length > 25); 27 | } 28 | 29 | public static bool AreAllNamesValid(string[] names) 30 | { 31 | foreach (var name in names) 32 | { 33 | if (char.IsLower(name[0])) 34 | { 35 | return false; 36 | } 37 | if (name.Length < 2) 38 | { 39 | return false; 40 | } 41 | if (name.Length > 25) 42 | { 43 | return false; 44 | } 45 | } 46 | return true; 47 | } 48 | 49 | public enum PetType 50 | { 51 | Cat, 52 | Dog, 53 | Fish 54 | } 55 | 56 | public class Pet 57 | { 58 | public int Id { get; } 59 | public string Name { get; } 60 | public PetType PetType { get; } 61 | public float Weight { get; } 62 | 63 | public Pet(int id, string name, PetType petType, float weight) 64 | { 65 | Id = id; 66 | Name = name; 67 | PetType = petType; 68 | Weight = weight; 69 | } 70 | 71 | public override string ToString() 72 | { 73 | return $"Id: {Id}, Name: {Name}, Type: {PetType}, Weight: {Weight}"; 74 | } 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /ExercisesSolutions/Average.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace ExercisesSolutions 6 | { 7 | public static class Average 8 | { 9 | //Coding Exercise 1 10 | public static float? AverageSnowFall(SnowFallData snowFallData) 11 | { 12 | return (snowFallData != null && 13 | snowFallData.MonthlySnowFallDataItems != null && 14 | snowFallData.MonthlySnowFallDataItems.Count() == 12) ? 15 | snowFallData.MonthlySnowFallDataItems.Average( 16 | snowFallDataItem => snowFallDataItem.SnowfallInCentimeters) : 17 | null; 18 | } 19 | 20 | //Coding Exercise 2 21 | public static double MaxAverageOfMarks(IEnumerable students) 22 | { 23 | return students.Any() ? 24 | students.Max(student => student.Marks.Any() ? student.Marks.Average() : 0) : 25 | 0; 26 | } 27 | 28 | //Refactoring challenge 29 | public static float CalculateAverageHeight_Refactored( 30 | List heights, float defaultIfNull) 31 | { 32 | return heights == null || !heights.Any() ? 33 | 0 : 34 | heights.Average(height => height ?? defaultIfNull); 35 | } 36 | 37 | //do not modify this method 38 | public static float CalculateAverageHeight( 39 | List heights, float defaultIfNull) 40 | { 41 | if (heights == null || heights.Count == 0) 42 | { 43 | return 0; 44 | } 45 | var sum = 0f; 46 | foreach (var height in heights) 47 | { 48 | if (height == null) 49 | { 50 | sum += defaultIfNull; 51 | } 52 | else 53 | { 54 | sum += height.Value; 55 | } 56 | } 57 | return sum / heights.Count; 58 | } 59 | 60 | public class Student 61 | { 62 | public IEnumerable Marks { get; set; } 63 | } 64 | 65 | public class SnowFallData 66 | { 67 | public int Year { get; set; } 68 | public List MonthlySnowFallDataItems { get; set; } 69 | } 70 | 71 | public class MonthlySnowFallData 72 | { 73 | public int Month { get; set; } 74 | public float SnowfallInCentimeters { get; set; } 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /ExercisesSolutions/Contains.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace ExercisesSolutions 6 | { 7 | public static class Contains 8 | { 9 | //Coding Exercise 1 10 | public static bool IsAppointmentDateAvailable( 11 | DateTime date, IEnumerable existingAppointmentDates) 12 | { 13 | return !existingAppointmentDates.Contains(date); 14 | } 15 | 16 | //Coding Exercise 2 17 | public static int CountFriendsOf(Friend friend, IEnumerable people) 18 | { 19 | return people.Count(person => person.Friends.Contains(friend)); 20 | } 21 | 22 | //Refactoring challenge 23 | public static bool ContainsBannedWords_Refactored( 24 | IEnumerable words, IEnumerable bannedWords) 25 | { 26 | return words.Any(word => bannedWords.Contains(word)); 27 | } 28 | 29 | //do not modify this method 30 | public static bool ContainsBannedWords( 31 | IEnumerable words, IEnumerable bannedWords) 32 | { 33 | foreach (var word in words) 34 | { 35 | foreach (var bannedWord in bannedWords) 36 | { 37 | if (word == bannedWord) 38 | { 39 | return true; 40 | } 41 | } 42 | } 43 | return false; 44 | } 45 | 46 | public class Person 47 | { 48 | public string Name { get; } 49 | public IEnumerable Friends { get; } 50 | 51 | public Person(string name, IEnumerable friends) 52 | { 53 | Name = name; 54 | Friends = friends; 55 | } 56 | } 57 | 58 | public class Friend 59 | { 60 | public string Name { get; } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /ExercisesSolutions/Count.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace ExercisesSolutions 5 | { 6 | public static class Count 7 | { 8 | //Coding Exercise 1 9 | public static int CountAllLongWords(IEnumerable words) 10 | { 11 | return words.Count(word => word.Length > 10); 12 | } 13 | 14 | //Coding Exercise 2 15 | public static bool AreThereFewerOddThanEvenNumbers( 16 | IEnumerable numbers) 17 | { 18 | return numbers.Count(number => number % 2 == 0) > 19 | numbers.Count(number => number % 2 != 0); 20 | } 21 | 22 | //Refactoring challenge 23 | public static bool IsAnySequenceTooLong_Refactored( 24 | IEnumerable> numberSequences, int maxLength) 25 | { 26 | return numberSequences.Any( 27 | numberSequence => numberSequence.Count() > maxLength); 28 | } 29 | 30 | //do not modify this method 31 | public static bool IsAnySequenceTooLong( 32 | IEnumerable> numberSequences, int maxLength) 33 | { 34 | foreach (var numberSequence in numberSequences) 35 | { 36 | var count = 0; 37 | foreach (var number in numberSequence) 38 | { 39 | ++count; 40 | } 41 | if (count > maxLength) 42 | { 43 | return true; 44 | } 45 | } 46 | return false; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /ExercisesSolutions/Distinct.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace ExercisesSolutions 5 | { 6 | public static class Distinct 7 | { 8 | //Coding Exercise 1 9 | public static bool AreAllUnique(IEnumerable collection) 10 | { 11 | return collection.Distinct().Count() == collection.Count(); 12 | } 13 | 14 | //Coding Exercise 2 15 | public static IEnumerable GetCollectionWithMostDuplicates( 16 | IEnumerable> collections) 17 | { 18 | return collections 19 | .OrderBy(collection => collection.Count() - collection.Distinct().Count()) 20 | .ThenByDescending(collection => collection.Count()) 21 | .LastOrDefault(); 22 | } 23 | 24 | //Refactoring challenge 25 | public static IEnumerable GetWordsShorterThan5Letters_Refactored( 26 | IEnumerable words) 27 | { 28 | return words.Distinct().Where(word => word.Length < 5); 29 | } 30 | 31 | //do not modify this method 32 | public static IEnumerable GetWordsShorterThan5Letters( 33 | IEnumerable words) 34 | { 35 | var result = new List(); 36 | foreach (var word in words) 37 | { 38 | if (word.Length < 5 && !result.Contains(word)) 39 | { 40 | result.Add(word); 41 | } 42 | } 43 | return result; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /ExercisesSolutions/ElementAt.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace ExercisesSolutions 6 | { 7 | public static class ElementAt 8 | { 9 | //Coding Exercise 1 10 | public static bool IsTheNumberAtIndexTheLargest( 11 | IEnumerable numbers, int index) 12 | { 13 | if (index < 0 || index >= numbers.Count()) 14 | { 15 | return false; 16 | } 17 | return numbers.All(number => number <= numbers.ElementAt(index)); 18 | 19 | //alternative solution 20 | //return numbers.Max() == numbers.ElementAt(index); 21 | } 22 | 23 | //Coding Exercise 2 24 | public static string FormatPetDataAtIndex( 25 | IEnumerable pets, int index) 26 | { 27 | var pet = pets.ElementAtOrDefault(index); 28 | return pet == null ? 29 | $"Pet data is missing for index {index}" : 30 | $"Pet name: {pet.Name}"; 31 | } 32 | 33 | //Refactoring challenge 34 | public static bool IsEmptyAtIndex_Refactored(IEnumerable words, int index) 35 | { 36 | return string.IsNullOrEmpty(words.ElementAtOrDefault(index)); 37 | } 38 | 39 | //do not modify this method 40 | public static bool IsEmptyAtIndex(IEnumerable words, int index) 41 | { 42 | var array = words.ToArray(); 43 | if (index < 0 || index >= array.Length) 44 | { 45 | return true; 46 | } 47 | if (string.IsNullOrEmpty(array[index])) 48 | { 49 | return true; 50 | } 51 | return false; 52 | } 53 | 54 | public class Pet 55 | { 56 | public string Name { get; set; } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /ExercisesSolutions/ExercisesSolutions.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net9.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /ExercisesSolutions/GeneratingNewCollection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace ExercisesSolutions 6 | { 7 | public static class GeneratingNewCollection 8 | { 9 | //Coding Exercise 1 10 | public static Dictionary NewYearsEvesSince( 11 | int initialYear, int yearsCount) 12 | { 13 | return 14 | Enumerable.Range(initialYear, yearsCount) 15 | .ToDictionary(year => year, 16 | year => new DateTime(year, 12, 31).DayOfWeek.ToString()); 17 | } 18 | 19 | //Coding Exercise 2 20 | public static string BuildTree(int levels) 21 | { 22 | return string.Join(Environment.NewLine, Enumerable.Range(1, levels) 23 | .Select(level => 24 | string.Join("", Enumerable.Repeat("*", level)))); 25 | } 26 | 27 | //Refactoring challenge 28 | public static IEnumerable DoubleLetters_Refactored(int countOfLetters) 29 | { 30 | const int CountOfLettersInEnglishAlphabet = 26; 31 | var finalCountOfLetters = Math.Min( 32 | countOfLetters, 33 | CountOfLettersInEnglishAlphabet); 34 | 35 | var allLetters = Enumerable 36 | .Range('A', finalCountOfLetters) 37 | .Select(i => (char)i); 38 | 39 | return allLetters.SelectMany( 40 | letter => allLetters, (first, second) => $"{first}{second}"); 41 | } 42 | 43 | //do not modify this method 44 | public static IEnumerable DoubleLetters(int countOfLetters) 45 | { 46 | const int CountOfLettersInEnglishAlphabet = 26; 47 | var finalCountOfLetters = Math.Min( 48 | countOfLetters, 49 | CountOfLettersInEnglishAlphabet); 50 | 51 | var allLetters = new List(); 52 | var letter = 'A'; 53 | for (int i = 0; i < finalCountOfLetters; ++i) 54 | { 55 | allLetters.Add(letter); 56 | letter++; 57 | } 58 | 59 | var result = new List(); 60 | foreach (var firstLetter in allLetters) 61 | { 62 | foreach (var secondLetter in allLetters) 63 | { 64 | result.Add($"{firstLetter}{secondLetter}"); 65 | } 66 | } 67 | return result; 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /ExercisesSolutions/OfType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace ExercisesSolutions 6 | { 7 | public static class OfType 8 | { 9 | //Coding Exercise 1 10 | public static int? GetTheFirstInteger(IEnumerable objects) 11 | { 12 | return objects.OfType().FirstOrDefault(); 13 | } 14 | 15 | //Coding Exercise 2 16 | public static bool AreAllStringsUpperCase(IEnumerable objects) 17 | { 18 | return objects.OfType().All(text => text.ToUpper() == text); 19 | } 20 | 21 | //Refactoring challenge 22 | public static DateTime? GetTheLatestDate_Refactored(IEnumerable objects) 23 | { 24 | return objects.OfType().Max(); 25 | } 26 | 27 | //do not modify this method 28 | public static DateTime? GetTheLatestDate(IEnumerable objects) 29 | { 30 | DateTime? lastDate = null; 31 | foreach (var obj in objects) 32 | { 33 | var dateTime = obj as DateTime?; 34 | if (dateTime != null) 35 | { 36 | if (lastDate == null || lastDate < dateTime) 37 | { 38 | lastDate = dateTime; 39 | } 40 | } 41 | } 42 | return lastDate; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /ExercisesSolutions/OrderBy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace ExercisesSolutions 6 | { 7 | public static class OrderBy 8 | { 9 | //Coding Exercise 1 10 | public static IEnumerable OrderFromLongestToShortest( 11 | IEnumerable words) 12 | { 13 | return words.OrderByDescending(word => word.Length); 14 | } 15 | 16 | //Coding Exercise 2 17 | public static IEnumerable FirstEvenThenOddDescending( 18 | IEnumerable numbers) 19 | { 20 | return numbers 21 | .OrderBy(number => number % 2 != 0) 22 | .ThenByDescending(number => number); 23 | } 24 | 25 | //Refactoring challenge 26 | public static IEnumerable OrderByMonth_Refactored( 27 | List dates) 28 | { 29 | return dates.OrderBy(date => date.Month); 30 | } 31 | 32 | //do not modify this method 33 | public static IEnumerable OrderByMonth(List dates) 34 | { 35 | dates.Sort((left, right) => 36 | { 37 | return left.Month.CompareTo(right.Month); 38 | }); 39 | return dates; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /ExercisesSolutions/OrderByQuerySyntax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace ExercisesSolutions 6 | { 7 | public static class OrderByQuerySyntax 8 | { 9 | //Coding Exercise 1 10 | public static IEnumerable 11 | OrderFromLongestToShortest( 12 | IEnumerable timeSpans) 13 | { 14 | return from timeSpan in timeSpans 15 | orderby timeSpan descending 16 | select timeSpan; 17 | } 18 | 19 | //Coding Exercise 2 20 | public static IEnumerable OrderPoints( 21 | IEnumerable points) 22 | { 23 | return from point in points 24 | orderby point.X, point.Y 25 | select point; 26 | } 27 | 28 | //Refactoring challenge 29 | public static IEnumerable 30 | OrderDatesByDayOfWeek_Refactored( 31 | IEnumerable dates) 32 | { 33 | return from date in dates 34 | orderby date.DayOfWeek 35 | select date; 36 | } 37 | 38 | //do not modify this method 39 | public static IEnumerable 40 | OrderDatesByDayOfWeek( 41 | IEnumerable dates) 42 | { 43 | var result = dates.ToList(); 44 | result.Sort((left, right) => 45 | { 46 | return left.DayOfWeek.CompareTo(right.DayOfWeek); 47 | }); 48 | return result; 49 | } 50 | 51 | //do not modify this method 52 | 53 | public struct Point 54 | { 55 | public double X { get; } 56 | public double Y { get; } 57 | 58 | public Point(double x, double y) 59 | { 60 | X = x; 61 | Y = y; 62 | } 63 | 64 | public override string ToString() 65 | { 66 | return $"X: {X}, Y: {Y}"; 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /ExercisesSolutions/PrependAppend.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace ExercisesSolutions 6 | { 7 | public static class PrependAppend 8 | { 9 | //Coding Exercise 1 10 | public static IEnumerable AddStartAndEndMarkers(IEnumerable words) 11 | { 12 | const string Start = "START"; 13 | const string End = "END"; 14 | 15 | var withStart = words.First() == Start ? 16 | words : 17 | words.Prepend(Start); 18 | 19 | return withStart.Last() == End ? 20 | withStart : 21 | withStart.Append(End); 22 | } 23 | 24 | //Coding Exercise 2 25 | public static IEnumerable RemoveDuplicatesFromStartAndEnd( 26 | IEnumerable numbers) 27 | { 28 | if (numbers.Count() < 2) 29 | { 30 | return numbers; 31 | } 32 | var firstNumber = numbers.First(); 33 | var lastNumber = numbers.Last(); 34 | 35 | return numbers 36 | .Where(number => number != firstNumber) 37 | .Prepend(firstNumber) 38 | .Where(number => number != lastNumber) 39 | .Append(lastNumber); 40 | } 41 | 42 | //Refactoring challenge 43 | public static IEnumerable TrimSentenceAndChangeEndMarker_Refactored( 44 | IEnumerable words) 45 | { 46 | return words.TakeWhile(word => word != "The end").Append("END"); 47 | } 48 | 49 | //do not modify this method 50 | public static IEnumerable TrimSentenceAndChangeEndMarker(IEnumerable words) 51 | { 52 | var result = new List(); 53 | foreach (var word in words) 54 | { 55 | if (word != "The end") 56 | { 57 | result.Add(word); 58 | } 59 | else 60 | { 61 | break; 62 | } 63 | } 64 | result.Add("END"); 65 | return result; 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /ExercisesSolutions/Single.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace ExercisesSolutions 6 | { 7 | public static class Single 8 | { 9 | //Coding Exercise 1 10 | public static string GetTheOnlyUpperCaseWord(IEnumerable words) 11 | { 12 | return words.SingleOrDefault(word => word.ToUpper() == word); 13 | } 14 | 15 | //Coding Exercise 2 16 | public static IEnumerable GetSingleElementCollection( 17 | IEnumerable> numberCollections) 18 | { 19 | return numberCollections.Single(collection => collection.Count() == 1); 20 | } 21 | 22 | //Refactoring challenge 23 | public static DateTime? GetSingleDay_Refactored( 24 | IEnumerable dates, DayOfWeek dayOfWeek) 25 | { 26 | return dates.Count(date => date.DayOfWeek == dayOfWeek) == 1 ? 27 | dates.Single(date => date.DayOfWeek == dayOfWeek) : 28 | (DateTime?)null; 29 | } 30 | 31 | //do not modify this method 32 | public static DateTime? GetSingleDay( 33 | IEnumerable dates, DayOfWeek dayOfWeek) 34 | { 35 | var count = 0; 36 | DateTime? result = null; 37 | foreach (var date in dates) 38 | { 39 | if (date.DayOfWeek == dayOfWeek) 40 | { 41 | result = date; 42 | count++; 43 | } 44 | } 45 | if (count == 1) 46 | { 47 | return result; 48 | } 49 | return null; 50 | } 51 | 52 | public enum PetType 53 | { 54 | Cat, 55 | Dog, 56 | Fish 57 | } 58 | 59 | public class Pet 60 | { 61 | public int Id { get; } 62 | public string Name { get; } 63 | public PetType PetType { get; } 64 | public float Weight { get; } 65 | 66 | public Pet(int id, string name, PetType petType, float weight) 67 | { 68 | Id = id; 69 | Name = name; 70 | PetType = petType; 71 | Weight = weight; 72 | } 73 | 74 | public override string ToString() 75 | { 76 | return $"Id: {Id}, Name: {Name}, Type: {PetType}, Weight: {Weight}"; 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /ExercisesSolutions/Skip.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace ExercisesSolutions 6 | { 7 | public static class Skip 8 | { 9 | //Coding Exercise 1 10 | public static double CalculateAverageMark(Student student) 11 | { 12 | return student.Marks.Count() > 2 ? 13 | student.Marks.OrderBy(mark => mark) 14 | .Skip(1) 15 | .SkipLast(1) 16 | .Average() : 17 | 0; 18 | } 19 | 20 | //Coding Exercise 2 21 | public static IEnumerable GetWordsBetweenStartAndEnd(List words) 22 | { 23 | var isValidCollection = 24 | words.Count(word => word == "START") == 1 && 25 | words.Count(word => word == "END") == 1 && 26 | words.IndexOf("START") < words.IndexOf("END"); 27 | 28 | return isValidCollection ? 29 | words.SkipWhile(word => word != "START").Skip(1).TakeWhile(word => word != "END") : 30 | new string[0]; 31 | } 32 | 33 | //Refactoring challenge 34 | public static IEnumerable GetAllAfterFirstDividableBy100_Refactored( 35 | IEnumerable numbers) 36 | { 37 | return numbers.SkipWhile(number => number % 100 != 0); 38 | } 39 | 40 | //do not modify this method 41 | public static IEnumerable GetAllAfterFirstDividableBy100(IEnumerable numbers) 42 | { 43 | var result = new List(); 44 | bool startAdding = false; 45 | foreach (var number in numbers) 46 | { 47 | if (!startAdding && number % 100 == 0) 48 | { 49 | startAdding = true; 50 | } 51 | if (startAdding) 52 | { 53 | result.Add(number); 54 | } 55 | } 56 | return result; 57 | } 58 | 59 | public class Student 60 | { 61 | public IEnumerable Marks { get; set; } 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /ExercisesSolutions/Sum.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace ExercisesSolutions 6 | { 7 | public static class Sum 8 | { 9 | //Coding Exercise 1 10 | public static int TotalLength(IEnumerable words) 11 | { 12 | return words.Sum(word => word.Length); 13 | } 14 | 15 | //Coding Exercise 2 16 | public static double AverageSum( 17 | IEnumerable> collectionsOfNumbers) 18 | { 19 | return collectionsOfNumbers.Average( 20 | singleCollection => singleCollection.Sum()); 21 | } 22 | 23 | //Refactoring challenge 24 | public static bool HasAnyStudentSumOfMarksLargerThan100_Refactored( 25 | IEnumerable students) 26 | { 27 | return students.Any(student => student.Marks.Sum() > 100); 28 | } 29 | 30 | //do not modify this method 31 | public static bool HasAnyStudentSumOfMarksLargerThan100( 32 | IEnumerable students) 33 | { 34 | foreach (var student in students) 35 | { 36 | var sumOfMarks = 0; 37 | foreach (var mark in student.Marks) 38 | { 39 | sumOfMarks += mark; 40 | } 41 | if (sumOfMarks > 100) 42 | { 43 | return true; 44 | } 45 | } 46 | return false; 47 | } 48 | 49 | public class Student 50 | { 51 | public IEnumerable Marks { get; set; } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /ExercisesSolutions/Take.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace ExercisesSolutions 6 | { 7 | public static class Take 8 | { 9 | //Coding Exercise 1 10 | public static IEnumerable TakeSome(IEnumerable numbers) 11 | { 12 | return numbers.Count() < 10 ? 13 | numbers.Take(3) : 14 | numbers.Count() < 100 ? numbers.Take(30) : numbers; 15 | } 16 | 17 | //Coding Exercise 2 18 | public static IEnumerable GetGivenPercentOfHeaviestPets( 19 | IEnumerable pets, int percent) 20 | { 21 | return pets 22 | .OrderByDescending(pet => pet.Weight) 23 | .Take(pets.Count() * percent / 100); 24 | } 25 | 26 | //Refactoring challenge 27 | public static IEnumerable GetDatesBeforeXXCentury_Refactored( 28 | IEnumerable dates) 29 | { 30 | return dates.TakeWhile(date => date.Year < 1901); 31 | } 32 | 33 | //do not modify this method 34 | public static IEnumerable GetDatesBeforeXXCentury( 35 | IEnumerable dates) 36 | { 37 | var result = new List(); 38 | foreach (var date in dates) 39 | { 40 | if (date.Year < 1901) 41 | { 42 | result.Add(date); 43 | } 44 | else 45 | { 46 | break; 47 | } 48 | } 49 | return result; 50 | } 51 | 52 | public class Pet 53 | { 54 | public string Name { get; } 55 | public float Weight { get; } 56 | 57 | public Pet(string name, float weight) 58 | { 59 | Name = name; 60 | Weight = weight; 61 | } 62 | 63 | public override string ToString() 64 | { 65 | return $" Name: {Name}, Weight: {Weight}"; 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /ExercisesSolutions/Zip.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace ExercisesSolutions 6 | { 7 | public static class Zip 8 | { 9 | //Coding Exercise 1 10 | public static IEnumerable BuildDates( 11 | IEnumerable years, 12 | IEnumerable months, 13 | IEnumerable days) 14 | { 15 | return years.Zip(months, 16 | (year, month) => new { year, month }).Zip(days, 17 | (yearMonth, day) => new DateTime( 18 | yearMonth.year, yearMonth.month, day)) 19 | .OrderBy(date => date); 20 | } 21 | 22 | //Coding Exercise 2 23 | public static IEnumerable 24 | GetDaysDifferencesBetweenDates( 25 | IEnumerable dates) 26 | { 27 | return dates.Zip(dates.Skip(1), 28 | (first, second) => $"It's been " + 29 | $"{(second - first).TotalDays} days " + 30 | $"between {first.ToString("yyyy-MM-dd")} " + 31 | $"and {second.ToString("yyyy-MM-dd")}"); 32 | } 33 | 34 | //Refactoring challenge 35 | public static IEnumerable MakeList_Refactored(IEnumerable words) 36 | { 37 | return Enumerable 38 | .Range('A', words.Count()) 39 | .Select(letter => (char)letter) 40 | .Zip(words, (letter, word) => $"{letter}) {word}"); 41 | } 42 | 43 | //do not modify this method 44 | public static IEnumerable MakeList(IEnumerable words) 45 | { 46 | var result = new List(); 47 | char letter = 'A'; 48 | foreach (var word in words) 49 | { 50 | result.Add($"{letter}) {word}"); 51 | letter++; 52 | } 53 | return result; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /ExercisesTests/Aggregate_Exercise1_Tests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using static ExercisesTests.Utilities.TestUtilities; 3 | using Exercises; 4 | using System; 5 | 6 | namespace ExercisesTests 7 | { 8 | [TestFixture] 9 | public class Aggregate_Exercise1_Tests 10 | { 11 | [Test] 12 | public void ShallCalculateTotalActivityDurationCorrectly1() 13 | { 14 | var input = new[] { 10, 50, 121 }; 15 | var result = Aggregate.TotalActivityDuration(input); 16 | var expectedResult = TimeSpan.FromSeconds(181); 17 | Assert.AreEqual(expectedResult, result, $"For input '{EnumerableToString(input)}' the result shall be '{expectedResult}' but it was '{result}'"); 18 | } 19 | 20 | [Test] 21 | public void ShallCalculateTotalActivityDurationCorrectly2() 22 | { 23 | var input = new[] { 20, 0, 10, 50, 121 }; 24 | var result = Aggregate.TotalActivityDuration(input); 25 | var expectedResult = TimeSpan.FromSeconds(201); 26 | Assert.AreEqual(expectedResult, result, $"For input '{EnumerableToString(input)}' the result shall be '{expectedResult}' but it was '{result}'"); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ExercisesTests/Aggregate_Exercise2_Tests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using Exercises; 3 | using System; 4 | 5 | namespace ExercisesTests 6 | { 7 | [TestFixture] 8 | public class Aggregate_Exercise2_Tests 9 | { 10 | [Test] 11 | public void FiveCount() 12 | { 13 | var result = Aggregate.PrintAlphabet(5); 14 | var expectedResult = "a,b,c,d,e"; 15 | Assert.AreEqual(expectedResult, result, $"For count 5 the result shall be '{expectedResult}' but it was '{result}'"); 16 | } 17 | 18 | [Test] 19 | public void OneCount() 20 | { 21 | var result = Aggregate.PrintAlphabet(1); 22 | var expectedResult = "a"; 23 | Assert.AreEqual(expectedResult, result, $"For count ` the result shall be '{expectedResult}' but it was '{result}'"); 24 | } 25 | 26 | [TestCase(0)] 27 | [TestCase(-1)] 28 | [TestCase(27)] 29 | public void InvalidCount(int count) 30 | { 31 | Assert.Throws(() => Aggregate.PrintAlphabet(count), $"For count {count} ArgumentException should be thrown"); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ExercisesTests/All_Exercise1_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using static ExercisesTests.Utilities.TestUtilities; 4 | 5 | namespace ExercisesTests 6 | { 7 | [TestFixture] 8 | public class All_Exercise1_Tests 9 | { 10 | [Test] 11 | public void NotAllAreDivisibleBy10() 12 | { 13 | var input = new[] { 10, 11, 12 }; 14 | Assert.False(All.AreAllNumbersDivisibleBy10(input), 15 | $"Test failed for numbers {EnumerableToString(input)}, " + 16 | $"because the AreAllNumbersDivisibleBy10 method result was True," + 17 | $" and 11 and 12 are not divisible by 10"); 18 | } 19 | 20 | [Test] 21 | public void AllAreDivisibleBy10() 22 | { 23 | var input = new[] { 10, 20, 30 }; 24 | Assert.True(All.AreAllNumbersDivisibleBy10(input), 25 | $"Test failed for numbers {EnumerableToString(input)}, " + 26 | $"because the AreAllNumbersDivisibleBy10 method result was False, " + 27 | $"and they are all divisible by 10"); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /ExercisesTests/All_Exercise2_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using System.Collections.Generic; 4 | using static ExercisesTests.Utilities.TestUtilities; 5 | using Pet = Exercises.All.Pet; 6 | using PetType = Exercises.All.PetType; 7 | 8 | namespace ExercisesTests 9 | { 10 | [TestFixture] 11 | public class All_Exercise2_Tests 12 | { 13 | [Test] 14 | public void AllAreOfTheSameType() 15 | { 16 | IEnumerable pets = new[] 17 | { 18 | new Pet(4, "Taiga", PetType.Dog, 35f), 19 | new Pet(5, "Rex", PetType.Dog, 40f), 20 | new Pet(6, "Lucky", PetType.Dog, 5f) 21 | }; 22 | 23 | Assert.True(All.AreAllPetsOfTheSameType(pets), 24 | $"The test failed because the result of " + 25 | $"the AreAllPetsOfTheSameType was False, " + 26 | $"and all those pets are of the same type: {EnumerableToString(pets)}"); 27 | } 28 | 29 | [TestCase(PetType.Dog)] 30 | [TestCase(PetType.Cat)] 31 | [TestCase(PetType.Fish)] 32 | public void AllAreOfTheSameType_SinglePet(PetType petType) 33 | { 34 | IEnumerable pets = new[] 35 | { 36 | new Pet(4, "Taiga", petType, 35f) 37 | }; 38 | 39 | Assert.True(All.AreAllPetsOfTheSameType(pets), 40 | $"The test failed because the result of the AreAllPetsOfTheSameType was False," + 41 | $" and all those pets are of the same type: {string.Join(", ", pets)}"); 42 | } 43 | 44 | [Test] 45 | public void AreOfDifferentTypes() 46 | { 47 | IEnumerable pets = new[] 48 | { 49 | new Pet(3, "Ed", PetType.Cat, 0.7f), 50 | new Pet(4, "Taiga", PetType.Dog, 35f), 51 | new Pet(5, "Rex", PetType.Dog, 40f) 52 | }; 53 | 54 | Assert.False(All.AreAllPetsOfTheSameType(pets), 55 | $"The test failed because the result of " + 56 | $"the AreAllPetsOfTheSameType was True, " + 57 | $"and those pets are not of the same type: {EnumerableToString(pets)}"); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /ExercisesTests/All_RefactoringChallenge_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using System.Collections.Generic; 4 | using static ExercisesTests.Utilities.TestUtilities; 5 | 6 | namespace ExercisesTests 7 | { 8 | [TestFixture] 9 | public class All_RefactoringChallenge_Tests 10 | { 11 | [Test] 12 | public void WordsOfTheSameLengthEmptyList_Refactored() 13 | { 14 | var words = new List { }; 15 | 16 | Assert.True(All.AreAllWordsOfTheSameLength_Refactored(words), 17 | $"The test failed because the result was False, " + 18 | $"and for an empty input List it should be True"); 19 | } 20 | 21 | [Test] 22 | public void WordsOfTheSameLengthEmptyList() 23 | { 24 | var words = new List { }; 25 | Assert.True(All.AreAllWordsOfTheSameLength(words), 26 | $"The test failed because the result was False, " + 27 | $"and for empty input List it should be True"); 28 | } 29 | 30 | [Test] 31 | public void WordsOfTheSameLength_Refactored() 32 | { 33 | var words = new List { "bee", "fox", "jay" }; 34 | Assert.True(All.AreAllWordsOfTheSameLength_Refactored(words), 35 | $"The test failed because the result was False, " + 36 | $"and all those words are of the same length: {EnumerableToString(words)}"); 37 | } 38 | 39 | [Test] 40 | public void WordsOfTheSameLength() 41 | { 42 | var words = new List { "bee", "fox", "jay" }; 43 | Assert.True(All.AreAllWordsOfTheSameLength(words), 44 | $"The test failed because the result was False, " + 45 | $"and all those words are of the same length: {EnumerableToString(words)}"); 46 | } 47 | 48 | [Test] 49 | public void WordsOfDifferentLengths_Refactored() 50 | { 51 | var words = new List { "bee", "whale", "jay" }; 52 | Assert.False(All.AreAllWordsOfTheSameLength_Refactored(words), 53 | $"The test failed because the result was True, " + 54 | $"and those words are not of the same length: {EnumerableToString(words)}"); 55 | } 56 | 57 | [Test] 58 | public void WordsOfDifferentLengths() 59 | { 60 | var words = new List { "bee", "whale", "jay" }; 61 | Assert.False(All.AreAllWordsOfTheSameLength(words), 62 | $"The test failed because the result was True, " + 63 | $"and those words are not of the same length: {EnumerableToString(words)}"); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /ExercisesTests/Any_Exercise1_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using static ExercisesTests.Utilities.TestUtilities; 4 | 5 | namespace ExercisesTests 6 | { 7 | [TestFixture] 8 | public class Any_Exercise1_Tests 9 | { 10 | [Test] 11 | public void WithNegativeNumbers() 12 | { 13 | var input = new[] { 10, -1, 1, 12 }; 14 | Assert.True( 15 | Any.IsAnyNumberNegative(new[] { 10, -1, 1, 12 }), 16 | $"The result should be True for numbers: {EnumerableToString(input)}"); 17 | } 18 | 19 | [Test] 20 | public void WithoutNegativeNumbers() 21 | { 22 | var input = new[] { 10, 1, 12 }; 23 | 24 | Assert.False(Any.IsAnyNumberNegative(new[] { 10, 1, 12 }), 25 | $"The result should be False for numbers: {EnumerableToString(input)}"); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ExercisesTests/Any_Exercise2_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using System.Collections.Generic; 4 | using static ExercisesTests.Utilities.TestUtilities; 5 | using Pet = Exercises.Any.Pet; 6 | using PetType = Exercises.Any.PetType; 7 | 8 | namespace ExercisesTests 9 | { 10 | [TestFixture] 11 | public class Any_Exercise2_Tests 12 | { 13 | [Test] 14 | public void WithNoCats() 15 | { 16 | IEnumerable pets = new[] 17 | { 18 | new Pet(5, "Rex", PetType.Dog, 40f), 19 | new Pet(6, "Lucky", PetType.Dog, 5f) 20 | }; 21 | 22 | Assert.False( 23 | Any.AreThereAnyBigCats(pets), 24 | $"AreThereAnyBigCats should return False for Pets: " + 25 | $"{EnumerableToString(pets, ";")}, as there is no Pet of type Cat" + 26 | $" and Weight over 2 kilos in this collection"); 27 | } 28 | 29 | [Test] 30 | public void WithNoBigCats() 31 | { 32 | IEnumerable pets = new[] 33 | { 34 | new Pet(6, "Lucky", PetType.Dog, 5f), 35 | new Pet(7, "Paws", PetType.Cat, 1f) 36 | }; 37 | 38 | Assert.False( 39 | Any.AreThereAnyBigCats(pets), 40 | $"AreThereAnyBigCats should return False for Pets: " + 41 | $"{EnumerableToString(pets, ";")}, as there is no Pet of type Cat " + 42 | $"and Weight over 2 kilos in this collection"); 43 | } 44 | 45 | [Test] 46 | public void WithBigCats() 47 | { 48 | IEnumerable pets = new[] 49 | { 50 | new Pet(6, "Lucky", PetType.Dog, 5f), 51 | new Pet(7, "Paws", PetType.Cat, 1f), 52 | new Pet(8, "Big Foot", PetType.Cat, 2.1f) 53 | }; 54 | 55 | Assert.True( 56 | Any.AreThereAnyBigCats(pets), 57 | $"AreThereAnyBigCats should return True for Pets: " + 58 | $"{EnumerableToString(pets, ";")}, as Big Foot is a Cat " + 59 | $"and it weighs over 2 kilos"); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /ExercisesTests/Average_Exercise1_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using System.Collections.Generic; 4 | using MonthlySnowFallData = Exercises.Average.MonthlySnowFallData; 5 | using SnowFallData = Exercises.Average.SnowFallData; 6 | 7 | namespace ExercisesTests 8 | { 9 | [TestFixture] 10 | public class Average_Exercise1_Tests 11 | { 12 | [Test] 13 | public void NullSnowFallData() 14 | { 15 | var result = Average.AverageSnowFall(null); 16 | Assert.Null(result, $"For null SnowFallData the result should be null"); 17 | } 18 | 19 | [Test] 20 | public void NullMonths() 21 | { 22 | var snowFallData = new SnowFallData(); 23 | var result = Average.AverageSnowFall(snowFallData); 24 | Assert.Null(result, $"For null MonthlySnowFallDataItems the result should be null"); 25 | } 26 | 27 | [Test] 28 | public void EmptyMonths() 29 | { 30 | var snowFallData = new SnowFallData() 31 | { 32 | MonthlySnowFallDataItems = new List() 33 | }; 34 | var result = Average.AverageSnowFall(snowFallData); 35 | Assert.Null(result, $"For empty MonthkySnowFallDataItems the result should be null"); 36 | } 37 | 38 | [Test] 39 | public void NonEmptyData() 40 | { 41 | var snowFallData = new SnowFallData() 42 | { 43 | MonthlySnowFallDataItems = new List 44 | { 45 | 46 | new MonthlySnowFallData {SnowfallInCentimeters = 11}, 47 | new MonthlySnowFallData {SnowfallInCentimeters = 22}, 48 | new MonthlySnowFallData {SnowfallInCentimeters = 10}, 49 | new MonthlySnowFallData {SnowfallInCentimeters = 9}, 50 | new MonthlySnowFallData {SnowfallInCentimeters = 5}, 51 | new MonthlySnowFallData {SnowfallInCentimeters = 0}, 52 | new MonthlySnowFallData {SnowfallInCentimeters = 0}, 53 | new MonthlySnowFallData {SnowfallInCentimeters = 1}, 54 | new MonthlySnowFallData {SnowfallInCentimeters = 5}, 55 | new MonthlySnowFallData {SnowfallInCentimeters = 18}, 56 | new MonthlySnowFallData {SnowfallInCentimeters = 19}, 57 | new MonthlySnowFallData {SnowfallInCentimeters = 32}, 58 | } 59 | }; 60 | var result = Average.AverageSnowFall(snowFallData); 61 | Assert.AreEqual(11, result, $"For snowfall of values 11, 22, 10, 9, 5, 0, 0, 1, 5, 18, 19, 32 the average should be 11"); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /ExercisesTests/Average_RefactoringChallenge_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using System.Collections.Generic; 4 | 5 | namespace ExercisesTests 6 | { 7 | [TestFixture] 8 | public class Average_RefactoringChallenge_Tests 9 | { 10 | [Test] 11 | public void NullInput_Refactored() 12 | { 13 | var result = Average.CalculateAverageHeight_Refactored(null, 0); 14 | Assert.AreEqual(0, result, $"For null input the result should be 0, but it was {result}"); 15 | } 16 | 17 | [Test] 18 | public void NullInput() 19 | { 20 | var result = Average.CalculateAverageHeight(null, 0); 21 | Assert.AreEqual(0, result, $"For null input the result should be 0, but it was {result}"); 22 | } 23 | 24 | [Test] 25 | public void EmptyInput_Refactored() 26 | { 27 | var result = Average.CalculateAverageHeight_Refactored(new List(), 0); 28 | Assert.AreEqual(0, result, $"For empty input the result should be 0, but it was {result}"); 29 | } 30 | 31 | [Test] 32 | public void EmptyNullInput() 33 | { 34 | var result = Average.CalculateAverageHeight(new List(), 0); 35 | Assert.AreEqual(0, result, $"For empty input the result should be 0, but it was {result}"); 36 | } 37 | 38 | [Test] 39 | public void DefaultShouldBeUsed_Refactored() 40 | { 41 | var result = Average.CalculateAverageHeight_Refactored(new List { null, 10 }, 0); 42 | Assert.AreEqual(5, result, $"For input (10, null) and default 0, the result should be 5, but it was {result}"); 43 | } 44 | 45 | [Test] 46 | public void DefaultShouldBeUsed() 47 | { 48 | var result = Average.CalculateAverageHeight(new List { null, 10 }, 0); 49 | Assert.AreEqual(5, result, $"For input (10, null) and default 0, the result should be 5, but it was {result}"); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /ExercisesTests/CollectionTypeChange_Exercise1_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using System.Collections.Generic; 4 | using static ExercisesTests.Utilities.TestUtilities; 5 | 6 | namespace ExercisesTests 7 | { 8 | [TestFixture] 9 | public class CollectionTypeChange_Exercise1_Tests 10 | { 11 | [Test] 12 | public void ParseToNumbersAndStoreInDictionaryShallWorkCorrectly() 13 | { 14 | var input = new string[] { "aaa", "1", "3", "bbb", "bbb" }; 15 | var result = CollectionTypeChange.ParseToNumbersAndStoreInDictionary(input); 16 | var expectedResult = new Dictionary 17 | { 18 | ["aaa"] = null, 19 | ["1"] = 1, 20 | ["3"] = 3, 21 | ["bbb"] = null, 22 | }; 23 | 24 | CollectionAssert.AreEqual(expectedResult, result, $"For INPUT " + 25 | $"{EnumerableToString(input)} the RESULT shall be " + 26 | $"{DictionaryToString(expectedResult)} BUT IT WAS " + 27 | $"{DictionaryToString(result)}"); 28 | } 29 | 30 | [Test] 31 | public void ParseToNumbersAndStoreInDictionaryShallWorkCorrectlyForSingleElement() 32 | { 33 | var input = new string[] { "3", "ARR" }; 34 | var result = CollectionTypeChange.ParseToNumbersAndStoreInDictionary(input); 35 | var expectedResult = new Dictionary 36 | { 37 | ["3"] = 3, 38 | ["ARR"] = null 39 | }; 40 | 41 | CollectionAssert.AreEqual(expectedResult, result, $"For INPUT " + 42 | $"{EnumerableToString(input)} the RESULT shall be " + 43 | $"{DictionaryToString(expectedResult)} BUT IT WAS " + 44 | $"{DictionaryToString(result)}"); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /ExercisesTests/CollectionTypeChange_Exercise2_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using static ExercisesTests.Utilities.TestUtilities; 4 | 5 | namespace ExercisesTests 6 | { 7 | [TestFixture] 8 | public class CollectionTypeChange_Exercise2_Tests 9 | { 10 | [Test] 11 | public void ShallCreateLookupProperly() 12 | { 13 | var input = new int[] { 1, 2, 4, 5, 6, 7, 9 }; 14 | 15 | var result = CollectionTypeChange.CreateLookupByDivisibilityBy2(input); 16 | var expectedResult1 = new int[] { 2, 4, 6 }; 17 | var expectedResult2 = new int[] { 1, 5, 7, 9 }; 18 | 19 | CollectionAssert.AreEqual(expectedResult1, result[true], 20 | $"result[true] shall be {EnumerableToString(expectedResult1)} but it was" + 21 | $" {EnumerableToString(result[true])}"); 22 | CollectionAssert.AreEqual(expectedResult2, result[false], 23 | $"result[false] shall be {EnumerableToString(expectedResult2)} but it was" + 24 | $" {EnumerableToString(result[false])}"); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ExercisesTests/ConcatUnion_Exercise1_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using System; 4 | using News = Exercises.ConcatUnion.News; 5 | using Priority = Exercises.ConcatUnion.Priority; 6 | 7 | namespace ExercisesTests 8 | { 9 | [TestFixture] 10 | public class ConcatUnion_Exercise1_Tests 11 | { 12 | [Test] 13 | public void ShallSelectNewsProperly() 14 | { 15 | var news = new[] 16 | { 17 | new News{ PublishingDate = new DateTime(2021, 10, 3), Priority = Priority.Medium} , 18 | new News{ PublishingDate = new DateTime(2021, 10, 2), Priority = Priority.High} , 19 | new News{ PublishingDate = new DateTime(2021, 10, 1), Priority = Priority.Low} , 20 | 21 | new News{ PublishingDate = new DateTime(2021, 10, 6), Priority = Priority.High} , 22 | new News{ PublishingDate = new DateTime(2021, 10, 5), Priority = Priority.Low} , 23 | new News{ PublishingDate = new DateTime(2021, 10, 4), Priority = Priority.Medium} , 24 | }; 25 | 26 | var expectedResult = new[] 27 | { 28 | new News{ PublishingDate = new DateTime(2021, 10, 6), Priority = Priority.High} , 29 | new News{ PublishingDate = new DateTime(2021, 10, 5), Priority = Priority.Low} , 30 | new News{ PublishingDate = new DateTime(2021, 10, 4), Priority = Priority.Medium} , 31 | new News{ PublishingDate = new DateTime(2021, 10, 2), Priority = Priority.High} , 32 | }; 33 | 34 | var result = ConcatUnion.SelectRecentAndImportant(news); 35 | 36 | var inputToString = string.Join(", ", news); 37 | var expectedResultToString = string.Join(", ", expectedResult); 38 | var resultToString = string.Join(", ", result); 39 | CollectionAssert.AreEqual(expectedResult, result, $"(See the exercise description for the input data) For input collection ({inputToString}) the result shall be ({expectedResultToString}) but it is ({resultToString})"); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /ExercisesTests/ConcatUnion_Exercise2_Tests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using Exercises; 3 | 4 | namespace ExercisesTests 5 | { 6 | [TestFixture] 7 | public class ConcatUnion_Exercise2_Tests 8 | { 9 | [Test] 10 | public void FoxTest() 11 | { 12 | var input = "f_o!_!x"; 13 | var result = ConcatUnion.CleanWord(input); 14 | var expectedResult = "fox_!"; 15 | Assert.AreEqual(expectedResult, result, $"For input '{input}' the result shall be '{expectedResult}', but it was '{result}'"); 16 | } 17 | 18 | [Test] 19 | public void DuckTest() 20 | { 21 | var input = "d_3uc(k))"; 22 | var result = ConcatUnion.CleanWord(input); 23 | var expectedResult = "duck_3()"; 24 | Assert.AreEqual(expectedResult, result, $"For input '{input}' the result shall be '{expectedResult}', but it was '{result}'"); 25 | } 26 | 27 | [Test] 28 | public void KittenTest() 29 | { 30 | var input = "Kit__ten"; 31 | var result = ConcatUnion.CleanWord(input); 32 | var expectedResult = "Kitten_"; 33 | Assert.AreEqual(expectedResult, result, $"For input '{input}' the result shall be '{expectedResult}', but it was '{result}'"); 34 | } 35 | 36 | [Test] 37 | public void EmptyInputTest() 38 | { 39 | var input = ""; 40 | var result = ConcatUnion.CleanWord(input); 41 | var expectedResult = ""; 42 | Assert.AreEqual(expectedResult, result, $"For an empty input the result shall be an empty string, but it was '{result}'"); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /ExercisesTests/ConcatUnion_RefactoringChallenge_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | 4 | namespace ExercisesTests 5 | { 6 | [TestFixture] 7 | public class ConcatUnion_RefactoringChallenge_Tests 8 | { 9 | [Test] 10 | public void GetPerfectSquaresTest() 11 | { 12 | var numbers1 = new int[] { 16, 99, 1, 3, 7, 9 }; 13 | var numbers2 = new int[] { 16, 8, 64, 100, 25 }; 14 | var expectedResult = new int[] { 1, 9, 16, 25, 64, 100 }; 15 | 16 | var result = ConcatUnion.GetPerfectSquares(numbers1, numbers2); 17 | 18 | var numbers1AsString = string.Join(", ", numbers1); 19 | var numbers2AsString = string.Join(", ", numbers2); 20 | var expectedResultAsString = string.Join(", ", expectedResult); 21 | var resultAsString = string.Join(", ", result); 22 | 23 | CollectionAssert.AreEqual(expectedResult, result, $"For input collections ({numbers1AsString}) and ({numbers2AsString}) the result shall be ({expectedResultAsString}) but it is ({resultAsString})"); 24 | } 25 | 26 | [Test] 27 | public void GetPerfectSquaresTest_Refactored() 28 | { 29 | var numbers1 = new int[] { 16, 99, 1, 3, 7, 9 }; 30 | var numbers2 = new int[] { 16, 8, 64, 100, 25 }; 31 | var expectedResult = new int[] { 1, 9, 16, 25, 64, 100 }; 32 | 33 | var result = ConcatUnion.GetPerfectSquares_Refactored(numbers1, numbers2); 34 | 35 | var numbers1AsString = string.Join(", ", numbers1); 36 | var numbers2AsString = string.Join(", ", numbers2); 37 | var expectedResultAsString = string.Join(", ", expectedResult); 38 | var resultAsString = string.Join(", ", result); 39 | 40 | CollectionAssert.AreEqual(expectedResult, result, $"For input collections ({numbers1AsString}) and ({numbers2AsString}) the result shall be ({expectedResultAsString}) but it is ({resultAsString})"); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /ExercisesTests/Contains_Exercise1_Tests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using System; 3 | using System.Linq; 4 | using Contains = Exercises.Contains; 5 | 6 | namespace ExercisesTests 7 | { 8 | [TestFixture] 9 | public class Contains_Exercise1_Tests 10 | { 11 | [Test] 12 | public void DateIsAvailable() 13 | { 14 | var date = new DateTime(2022, 1, 10); 15 | var dates = new[] 16 | { 17 | new DateTime(2022, 1, 11), 18 | new DateTime(2022, 1, 12) 19 | }; 20 | var datesAsString = string.Join(", ", dates.Select(d => d.ToString("d"))); 21 | var result = Contains.IsAppointmentDateAvailable(date, dates); 22 | Assert.True(result, $"The test failed because the date {date.ToString("d")} is not present amongst dates: {datesAsString}"); 23 | } 24 | 25 | [Test] 26 | public void DateIsNotAvailable() 27 | { 28 | var date = new DateTime(2022, 1, 10); 29 | var dates = new[] 30 | { 31 | new DateTime(2022, 1, 10), 32 | new DateTime(2022, 1, 12) 33 | }; 34 | var datesAsString = string.Join(", ", dates.Select(d => d.ToString("d"))); 35 | var result = Contains.IsAppointmentDateAvailable(date, dates); 36 | Assert.False(result, $"The test failed because the date {date.ToString("d")} is already present amongst dates: {datesAsString}"); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /ExercisesTests/Contains_Exercise2_Tests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using System.Collections.Generic; 3 | using Contains = Exercises.Contains; 4 | using Friend = Exercises.Contains.Friend; 5 | using Person = Exercises.Contains.Person; 6 | 7 | namespace ExercisesTests 8 | { 9 | [TestFixture] 10 | public class Contains_Exercise2_Tests 11 | { 12 | [Test] 13 | public void FriendWith3Friends() 14 | { 15 | var friend = new Friend(); 16 | var otherFriend = new Friend(); 17 | var people = new List 18 | { 19 | new Person("John", new [] {friend}), 20 | new Person("Mary", new [] {friend, otherFriend}), 21 | new Person("Jack", new [] {friend, otherFriend}), 22 | new Person("Martin", new [] {otherFriend}) 23 | }; 24 | 25 | var result = Contains.CountFriendsOf(friend, people); 26 | Assert.AreEqual(result, 3, $"The test failed, because the count of " + 27 | $"fiends is 3, and te result of the CountFriendsOf method was {result}"); 28 | } 29 | 30 | [Test] 31 | public void FriendWith1Friend() 32 | { 33 | var friend = new Friend(); 34 | var otherFriend = new Friend(); 35 | var people = new List 36 | { 37 | new Person("Mary", new [] {friend, otherFriend}), 38 | new Person("Martin", new [] {otherFriend}) 39 | }; 40 | 41 | var result = Contains.CountFriendsOf(friend, people); 42 | Assert.AreEqual(result, 1, $"The test failed, because the count of " + 43 | $"people is 1, and te result of the CountFriendsOf method was {result}"); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /ExercisesTests/Contains_RefactoringChallenge_Tests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using Contains = Exercises.Contains; 3 | 4 | namespace ExercisesTests 5 | { 6 | [TestFixture] 7 | public class Contains_RefactoringChallenge_Tests 8 | { 9 | [Test] 10 | public void ContainsBannedWords() 11 | { 12 | var bannedWords = new[] { "lollipop", "octopus", "badger" }; 13 | var words = new[] { "hello", "octopus" }; 14 | var wordsAsString = string.Join(", ", words); 15 | var bannedWordsAsString = string.Join(", ", bannedWords); 16 | var result = Contains.ContainsBannedWords(words, bannedWords); 17 | Assert.True(result, $"The test failed because the method result was False, yet words \"{wordsAsString}\" contain one or more of the banned words ({bannedWordsAsString})"); 18 | } 19 | 20 | [Test] 21 | public void ContainsBannedWords_Refactored() 22 | { 23 | var bannedWords = new[] { "lollipop", "octopus", "badger" }; 24 | var words = new[] { "hello", "octopus" }; 25 | var wordsAsString = string.Join(", ", words); 26 | var bannedWordsAsString = string.Join(", ", bannedWords); 27 | var result = Contains.ContainsBannedWords_Refactored(words, bannedWords); 28 | Assert.True(result, $"The test failed because the method result was False, yet words \"{wordsAsString}\" contain one or more of the banned words ({bannedWordsAsString})"); 29 | } 30 | 31 | [Test] 32 | public void DoNotContainBannedWords() 33 | { 34 | var bannedWords = new[] { "lollipop", "octopus", "badger" }; 35 | var words = new[] { "hello", "there" }; 36 | var wordsAsString = string.Join(", ", words); 37 | var bannedWordsAsString = string.Join(", ", bannedWords); 38 | var result = Contains.ContainsBannedWords(words, bannedWords); 39 | Assert.False(result, $"The test failed because the method result was True, yet words \"{wordsAsString}\" do not contain any of the banned words ({bannedWordsAsString})"); 40 | } 41 | 42 | [Test] 43 | public void DoNotContainBannedWords_Refactored() 44 | { 45 | var bannedWords = new[] { "lollipop", "octopus", "badger" }; 46 | var words = new[] { "hello", "there" }; 47 | var wordsAsString = string.Join(", ", words); 48 | var bannedWordsAsString = string.Join(", ", bannedWords); 49 | var result = Contains.ContainsBannedWords_Refactored(words, bannedWords); 50 | Assert.False(result, $"The test failed because the method result was True, yet words \"{wordsAsString}\" do not contain any of the banned words ({bannedWordsAsString})"); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /ExercisesTests/Count_Exercise1_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | 4 | namespace ExercisesTests 5 | { 6 | [TestFixture] 7 | public class Count_Exercise1_Tests 8 | { 9 | [Test] 10 | public void Exactly10Letters() 11 | { 12 | var words = new[] { "aaaaabbbbb", "abc" }; 13 | var wordsAsString = string.Join(", ", words); 14 | var result = Count.CountAllLongWords(words); 15 | Assert.AreEqual(result, 0, $"Test failed, because there are 0 words " + 16 | $"longer than 10 letters in the {wordsAsString} collection " + 17 | $"(aaaaabbbbb is exactly 10 letters long)"); 18 | } 19 | 20 | [Test] 21 | public void OneWordLongerThan10Letters() 22 | { 23 | var words = new[] { "aaaaabbbbbc", "abc" }; 24 | var wordsAsString = string.Join(", ", words); 25 | var result = Count.CountAllLongWords(words); 26 | Assert.AreEqual(result, 1, $"Test failed, because there is 1 word " + 27 | $"longer than 10 letters in the {wordsAsString} collection " + 28 | $"(aaaaabbbbbc is exactly 11 letters long)"); 29 | } 30 | 31 | [Test] 32 | public void TwoWordsLongerThan10Letters() 33 | { 34 | var words = new[] { "aaaaabbbbbc", "aaaaabbbbbccccc", "abc" }; 35 | var wordsAsString = string.Join(", ", words); 36 | var result = Count.CountAllLongWords(words); 37 | Assert.AreEqual(result, 2, $"Test failed, because there are 2 " + 38 | $"words longer than 10 letters in the {wordsAsString} collection"); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /ExercisesTests/Count_Exercise2_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | 4 | namespace ExercisesTests 5 | { 6 | [TestFixture] 7 | public class Count_Exercise2_Tests 8 | { 9 | [Test] 10 | public void MoreEvenThanOdd() 11 | { 12 | var numbers = new[] { 2, 3, 4, 5, 6 }; 13 | var numbersAsString = string.Join(", ", numbers); 14 | var result = Count.AreThereFewerOddThanEvenNumbers(numbers); 15 | Assert.True(result, $"The test failed for numbers {numbersAsString}. " + 16 | $"The method result was False, but it should be True"); 17 | } 18 | 19 | [Test] 20 | public void MoreOddThanEven() 21 | { 22 | var numbers = new[] { 3, 4, 5 }; 23 | var numbersAsString = string.Join(", ", numbers); 24 | var result = Count.AreThereFewerOddThanEvenNumbers(numbers); 25 | Assert.False(result, $"The test failed for numbers {numbersAsString}. " + 26 | $"The method result was True, but it should be False"); 27 | } 28 | 29 | [Test] 30 | public void TheSameCount() 31 | { 32 | var numbers = new[] { 2, 3, 4, 5 }; 33 | var numbersAsString = string.Join(", ", numbers); 34 | var result = Count.AreThereFewerOddThanEvenNumbers(numbers); 35 | Assert.False(result, $"The test failed for numbers {numbersAsString}. " + 36 | $"The method result was True, but it should be False"); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /ExercisesTests/Distinct_Exercise1_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | 4 | namespace ExercisesTests 5 | { 6 | [TestFixture] 7 | public class Distinct_Exercise1_Tests 8 | { 9 | [Test] 10 | public void AllAreUniqe() 11 | { 12 | var input = new int[] { 1, 2, 3, 4, 5 }; 13 | var result = Distinct.AreAllUnique(input); 14 | Assert.True(result, $"All elements of (1,2,3,4,5) are unique," + 15 | $" but the result was False"); 16 | } 17 | 18 | [Test] 19 | public void NotAllAreUniqe() 20 | { 21 | var input = new int[] { 1, 2, 3, 4, 4, 5 }; 22 | var result = Distinct.AreAllUnique(input); 23 | Assert.False(result, $"Not all elements of (1,2,3,4,4,5) are unique" + 24 | $" (4 is duplicated), but the result was True"); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ExercisesTests/Distinct_Exercise2_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | namespace ExercisesTests 7 | { 8 | [TestFixture] 9 | public class Distinct_Exercise2_Tests 10 | { 11 | [Test] 12 | public void FirstTest() 13 | { 14 | var collections = new List> 15 | { 16 | new List {1,2,3,4}, 17 | new List {1,2,3,3,4,4,4}, 18 | new List {1,2,3,3,4,4,4,5,6,7}, 19 | }; 20 | 21 | var expectedResult = collections[1]; 22 | var result = Distinct.GetCollectionWithMostDuplicates(collections); 23 | var resultAsString = string.Join(",", result); 24 | CollectionAssert.AreEqual(expectedResult, result, $"For input collections (1,2,3,4), (1,2,3,3,4,4,4), (1,2,3,3,4,4,4,5,6,7) the result collection shall be (1,2,3,3,4,4,4), but it was ({resultAsString})"); 25 | } 26 | 27 | [Test] 28 | public void SecondTest() 29 | { 30 | var collections = new List> 31 | { 32 | new List {1,2,3,3,4,4,4}, 33 | new List {1,2,3,4}, 34 | new List {1,2,3,3,4,4,4,5,6,7}, 35 | new List {1,2,3,4,4,4,5,6,7}, 36 | }; 37 | 38 | var expectedResult = collections[0]; 39 | var result = Distinct.GetCollectionWithMostDuplicates(collections); 40 | 41 | var resultAsString = string.Join(",", result); 42 | CollectionAssert.AreEqual(expectedResult, result, $"For input collections (1,2,3,3,4,4,4), (1,2,3,4), (1,2,3,3,4,4,4,5,6,7), (1,2,3,4,4,4,5,6,7) the result collection shall be (1,2,3,3,4,4,4), but it was ({resultAsString})"); 43 | } 44 | 45 | [Test] 46 | public void EmptyCollection() 47 | { 48 | try 49 | { 50 | var collections = new List> 51 | { 52 | }; 53 | 54 | var result = Distinct.GetCollectionWithMostDuplicates(collections); 55 | var resultAsString = result == null ? "null" : string.Join(",", result); 56 | CollectionAssert.AreEqual(null, result, $"For an empty input collection the result shall be null, but it was ({resultAsString})"); 57 | } 58 | catch (InvalidOperationException ex) 59 | { 60 | Assert.Fail($"For an empty input collection the result shall be null, but an exception was thrown: {ex.Message}"); 61 | } 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /ExercisesTests/ElementAt_Exercise1_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | 4 | namespace ExercisesTests 5 | { 6 | [TestFixture] 7 | public class ElementAt_Exercise1_Tests 8 | { 9 | [Test] 10 | public void EmptyCollection() 11 | { 12 | Assert.False(ElementAt.IsTheNumberAtIndexTheLargest(new int[0], 0), 13 | $"For an empty collection, the result shall be False"); 14 | } 15 | 16 | [Test] 17 | public void IndexPresent_NumberIsNotTheLargest() 18 | { 19 | var input = new int[] { 1, 2, 3, 4 }; 20 | 21 | Assert.False(ElementAt.IsTheNumberAtIndexTheLargest(input, 0), 22 | $"Number at index 0 (value: 1) is not the largest in the collection 1,2,3,4"); 23 | } 24 | 25 | [Test] 26 | public void NegativeIndex() 27 | { 28 | var input = new int[] { 1, 2, 4, 4 }; 29 | 30 | Assert.False(ElementAt.IsTheNumberAtIndexTheLargest(input, -1), 31 | $"For invalid index (in this case: -1) the result shall be False"); 32 | } 33 | 34 | [Test] 35 | public void IndexPresent_NumberIsTheLargest() 36 | { 37 | var input = new int[] { 1, 2, 3, 4 }; 38 | 39 | Assert.True(ElementAt.IsTheNumberAtIndexTheLargest(input, 3), 40 | $"Number at index 3 (value: 4) is the largest in the collection 1,2,3,4"); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /ExercisesTests/ElementAt_Exercise2_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using System.Collections.Generic; 4 | using Pet = Exercises.ElementAt.Pet; 5 | 6 | namespace ExercisesTests 7 | { 8 | [TestFixture] 9 | public class ElementAt_Exercise2_Tests 10 | { 11 | [Test] 12 | public void NoSuchPet() 13 | { 14 | var pets = new List(); 15 | var result = ElementAt.FormatPetDataAtIndex(pets, 0); 16 | Assert.AreEqual("Pet data is missing for index 0", result, "$For an empty collection and index 0, the result should be 'Pet data is missing for index 0'"); 17 | } 18 | 19 | [Test] 20 | public void PetIsPresent() 21 | { 22 | var pets = new List 23 | { 24 | new Pet {Name = "Hannibal"} 25 | }; 26 | var result = ElementAt.FormatPetDataAtIndex(pets, 0); 27 | Assert.AreEqual("Pet name: Hannibal", result, $"For a list of one pet named 'Hannibal' and for index 0, the result should be 'Pet name: Hannibal'"); 28 | } 29 | 30 | [Test] 31 | public void PetIsPresentButNull() 32 | { 33 | var pets = new List 34 | { 35 | null 36 | }; 37 | var result = ElementAt.FormatPetDataAtIndex(pets, 0); 38 | Assert.AreEqual("Pet data is missing for index 0", result, $"For a list of one pet named of null value and for index 0, the result should be 'Pet data is missing for index 0'"); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /ExercisesTests/ElementAt_RefactoringChallenge_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | 4 | namespace ExercisesTests 5 | { 6 | [TestFixture] 7 | public class ElementAt_RefactoringChallenge_Tests 8 | { 9 | [Test] 10 | public void IsEmptyAtIndex() 11 | { 12 | var words = new[] { "aaa", null, "bbb" }; 13 | var result = ElementAt.IsEmptyAtIndex(words, 1); 14 | Assert.True(result, $"For the collection (aaa, null, bbb) the value at index 1 is null or empty"); 15 | } 16 | 17 | [Test] 18 | public void IsEmptyAtIndex_Refactored() 19 | { 20 | var words = new[] { "aaa", null, "bbb" }; 21 | var result = ElementAt.IsEmptyAtIndex_Refactored(words, 1); 22 | Assert.True(result, $"For the collection (aaa, null, bbb) the value at index 1 is null or empty"); 23 | } 24 | 25 | [Test] 26 | public void IsNotEmptyAtIndex() 27 | { 28 | var words = new[] { "aaa", "bbb", "ccc" }; 29 | var result = ElementAt.IsEmptyAtIndex(words, 1); 30 | Assert.False(result, $"For the collection (aaa, bbb, ccc) the value at index 1 is not empty"); 31 | } 32 | 33 | [Test] 34 | public void IsNotEmptyAtIndex_Refactored() 35 | { 36 | var words = new[] { "aaa", "bbb", "ccc" }; 37 | var result = ElementAt.IsEmptyAtIndex_Refactored(words, 1); 38 | Assert.False(result, $"For the collection (aaa, bbb, ccc) the value at index 1 is not empty"); 39 | } 40 | 41 | [Test] 42 | public void InvalidIndex() 43 | { 44 | var words = new[] { "aaa", "bbb", "ccc" }; 45 | var result = ElementAt.IsEmptyAtIndex(words, -1); 46 | Assert.True(result, $"For the collection (aaa, bbb, ccc) the index -1 is not valid, and in this case we want to return True"); 47 | } 48 | 49 | [Test] 50 | public void InvalidIndex_Refactored() 51 | { 52 | var words = new[] { "aaa", "bbb", "ccc" }; 53 | var result = ElementAt.IsEmptyAtIndex_Refactored(words, -1); 54 | Assert.True(result, $"For the collection (aaa, bbb, ccc) the index -1 is not valid, and in this case we want to return True"); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /ExercisesTests/ExercisesTests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net9.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /ExercisesTests/FirstLast_Exercise1_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | namespace ExercisesTests 4 | { 5 | [TestFixture] 6 | public class FirstLast_Exercise1_Tests 7 | { 8 | [Test] 9 | public void NameIsPresent() 10 | { 11 | var words = new[] { "abc", "K", "MArtin", "John", "Jack", "bbb" }; 12 | var result = FirstLast.FindFirstNameInTheCollection(words); 13 | Assert.AreEqual("John", result, $"The first name in the collection (abc, K, MArtin, John, Jack, bbb) is John"); 14 | } 15 | 16 | [Test] 17 | public void NameIsNotPresent() 18 | { 19 | var words = new[] { "abc", "K", "bbb" }; 20 | var result = FirstLast.FindFirstNameInTheCollection(words); 21 | Assert.AreEqual(null, result, $"No word in the collection (abc, K, bbb) is a valid name"); 22 | } 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /ExercisesTests/FirstLast_Exercise2_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using System; 4 | using System.Collections.Generic; 5 | using Person = Exercises.FirstLast.Person; 6 | 7 | namespace ExercisesTests 8 | { 9 | [TestFixture] 10 | public class FirstLast_Exercise2_Tests 11 | { 12 | [Test] 13 | public void ShallFindYoungest_InNonEmptyCollection() 14 | { 15 | var people = new List 16 | { 17 | new Person ("John", new DateTime(1986, 3, 4)), 18 | new Person ("Stephanie", new DateTime(1990, 12, 4)), 19 | new Person ("Mark", new DateTime(1957, 1, 2)) 20 | }; 21 | var peopleAsString = string.Join(", ", people); 22 | var result = FirstLast.GetYoungest(people); 23 | Assert.AreEqual(people[1], result, $"The test failed, because the youngest person in ({peopleAsString}) collection is Stephanie, and the result is {result}"); 24 | } 25 | 26 | [Test] 27 | public void EmptyCollection() 28 | { 29 | var people = new List 30 | { 31 | }; 32 | var result = FirstLast.GetYoungest(people); 33 | Assert.AreEqual(null, result, "For empty collection the result should be null"); 34 | } 35 | } 36 | } 37 | 38 | -------------------------------------------------------------------------------- /ExercisesTests/GeneratingNewCollection_Exercise1_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using System.Collections.Generic; 4 | using static ExercisesTests.Utilities.TestUtilities; 5 | 6 | namespace ExercisesTests 7 | { 8 | [TestFixture] 9 | public class GeneratingNewCollection_Exercise1_Tests 10 | { 11 | [Test] 12 | public void ShallGet5EvesStartingOn1900Correctly() 13 | { 14 | var result = GeneratingNewCollection.NewYearsEvesSince(1900, 5); 15 | var expectedResult = new Dictionary 16 | { 17 | [1900] = "Monday", 18 | [1901] = "Tuesday", 19 | [1902] = "Wednesday", 20 | [1903] = "Thursday", 21 | [1904] = "Saturday" 22 | }; 23 | 24 | CollectionAssert.AreEqual(expectedResult, result, 25 | $"For initial year 1900 and 5 years in total, " + 26 | $"the days of week of the New Year's Eve were " + 27 | $"({DictionaryToString(expectedResult)}) but the result is " + 28 | $"({DictionaryToString(result)})"); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ExercisesTests/GeneratingNewCollection_Exercise2_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using System; 4 | 5 | namespace ExercisesTests 6 | { 7 | [TestFixture] 8 | public class GeneratingNewCollection_Exercise2_Tests 9 | { 10 | [Test] 11 | public void FiveLevels() 12 | { 13 | var result = GeneratingNewCollection.BuildTree(5); 14 | var expectedResult = @"* 15 | ** 16 | *** 17 | **** 18 | *****"; 19 | 20 | Assert.AreEqual(expectedResult, result, "Invalid tree for levels count 5"); 21 | } 22 | 23 | [Test] 24 | public void ZeroLevels() 25 | { 26 | var result = GeneratingNewCollection.BuildTree(0); 27 | var expectedResult = @""; 28 | 29 | Assert.AreEqual(expectedResult, result, "For levels count 0 the result shall be an empty string"); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ExercisesTests/GeneratingNewCollection_RefactoringChallenge_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using static ExercisesTests.Utilities.TestUtilities; 4 | 5 | namespace ExercisesTests 6 | { 7 | [TestFixture] 8 | public class GeneratingNewCollection_RefactoringChallenge_Tests 9 | { 10 | [Test] 11 | public void NonEmpty() 12 | { 13 | var result = GeneratingNewCollection.DoubleLetters(3); 14 | var expectedResult = new[] { "AA", "AB", "AC", "BA", "BB", "BC", "CA", "CB", "CC" }; 15 | 16 | CollectionAssert.AreEqual(expectedResult, result, $"For 3 first letters, the result shall be {EnumerableToString(expectedResult)} but it was {EnumerableToString(result)}"); 17 | } 18 | 19 | [Test] 20 | public void NonEmpty_Refactored() 21 | { 22 | var result = GeneratingNewCollection.DoubleLetters_Refactored(3); 23 | var expectedResult = new[] { "AA", "AB", "AC", "BA", "BB", "BC", "CA", "CB", "CC" }; 24 | 25 | CollectionAssert.AreEqual(expectedResult, result, $"For 3 first letters, the result shall be {EnumerableToString(expectedResult)} but it was {EnumerableToString(result)}"); 26 | } 27 | 28 | [Test] 29 | public void Empty() 30 | { 31 | var result = GeneratingNewCollection.DoubleLetters(0); 32 | var expectedResult = new string[0]; 33 | 34 | CollectionAssert.AreEqual(expectedResult, result, $"For 0 first letters, the result shall be empty, but it was {EnumerableToString(result)}"); 35 | } 36 | 37 | [Test] 38 | public void Empty_Refactored() 39 | { 40 | var result = GeneratingNewCollection.DoubleLetters_Refactored(0); 41 | var expectedResult = new string[0]; 42 | 43 | CollectionAssert.AreEqual(expectedResult, result, $"For 0 first letters, the result shall be empty, but it was {EnumerableToString(result)}"); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /ExercisesTests/GroupBy_QuerySyntax_Exercise1_Tests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using static ExercisesTests.Utilities.TestUtilities; 3 | using Exercises; 4 | 5 | namespace ExercisesTests 6 | { 7 | [TestFixture] 8 | public class GroupBy_QuerySyntax_Exercise1_Tests 9 | { 10 | [Test] 11 | public void GroupByFirstDigitShallWorkCorrectly1() 12 | { 13 | var numbers = new[] 14 | { 15 | 1, 11, 44, 4, 62, 672, 921 16 | }; 17 | 18 | var expectedResult = new[] 19 | { 20 | "FirstDigit: 1, numbers: 1,11", 21 | "FirstDigit: 4, numbers: 44,4", 22 | "FirstDigit: 6, numbers: 62,672", 23 | "FirstDigit: 9, numbers: 921" 24 | }; 25 | 26 | var result = GroupByQuerySyntax.GroupByFirstDigit(numbers); 27 | 28 | CollectionAssert.AreEqual(expectedResult, result, 29 | $"For INPUT {EnumerableToString(numbers)} the RESULT shall be " + 30 | $"'{EnumerableToString(expectedResult)}' BUT IT WAS " + 31 | $"'{EnumerableToString(result)}'"); 32 | } 33 | 34 | [Test] 35 | public void GroupByFirstDigitShallWorkCorrectly2() 36 | { 37 | var numbers = new[] 38 | { 39 | 9, 91, 9713, 994 40 | }; 41 | 42 | var expectedResult = new[] 43 | { 44 | "FirstDigit: 9, numbers: 9,91,9713,994", 45 | }; 46 | 47 | var result = GroupByQuerySyntax.GroupByFirstDigit(numbers); 48 | 49 | CollectionAssert.AreEqual(expectedResult, result, $"For INPUT " + 50 | $"{EnumerableToString(numbers)} the RESULT shall be " + 51 | $"'{EnumerableToString(expectedResult)}' BUT IT WAS " + 52 | $"'{EnumerableToString(result)}'"); 53 | } 54 | 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /ExercisesTests/GroupBy_QuerySyntax_Exercise2_Tests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using static ExercisesTests.Utilities.TestUtilities; 3 | using Exercises; 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | namespace ExercisesTests 8 | { 9 | [TestFixture] 10 | public class GroupBy_QuerySyntax_Exercise2_Tests 11 | { 12 | [Test] 13 | public void GroupByDayOfWeekShallWorkCorrectly1() 14 | { 15 | var input = new[] { 16 | new DateTime(2021, 10, 10), 17 | new DateTime(2021, 10, 17), 18 | new DateTime(2021, 10, 11), 19 | new DateTime(2021, 10, 4), 20 | new DateTime(2021, 10, 13), 21 | }; 22 | var result = GroupByQuerySyntax.GroupByDayOfWeek(input); 23 | var expectedResult = new Dictionary 24 | { 25 | [DayOfWeek.Sunday] = new DateTime(2021, 10, 17), 26 | [DayOfWeek.Monday] = new DateTime(2021, 10, 11), 27 | [DayOfWeek.Wednesday] = new DateTime(2021, 10, 13) 28 | }; 29 | 30 | CollectionAssert.AreEqual(expectedResult, result, $"For INPUT {EnumerableToString(input)} the RESULT shall be {DictionaryToString(expectedResult)} but it was {DictionaryToString(result)}"); 31 | } 32 | 33 | [Test] 34 | public void GroupByDayOfWeekShallWorkCorrectly2() 35 | { 36 | var input = new[] { 37 | new DateTime(2021, 10, 10), 38 | new DateTime(2021, 10, 17), 39 | new DateTime(2021, 10, 24), 40 | new DateTime(2021, 10, 4), 41 | new DateTime(2021, 10, 13), 42 | }; 43 | var result = GroupByQuerySyntax.GroupByDayOfWeek(input); 44 | var expectedResult = new Dictionary 45 | { 46 | [DayOfWeek.Sunday] = new DateTime(2021, 10, 24), 47 | [DayOfWeek.Monday] = new DateTime(2021, 10, 4), 48 | [DayOfWeek.Wednesday] = new DateTime(2021, 10, 13) 49 | }; 50 | 51 | CollectionAssert.AreEqual(expectedResult, result, $"For INPUT {EnumerableToString(input)} the RESULT shall be {DictionaryToString(expectedResult)} but it was {DictionaryToString(result)}"); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /ExercisesTests/Grouping_Exercise1_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using System; 4 | 5 | namespace ExercisesTests 6 | { 7 | [TestFixture] 8 | public class Grouping_Exercise1_Tests 9 | { 10 | [TestCase("Bumblebee", 'b')] 11 | [TestCase("eebelbmuB", 'e')] 12 | [TestCase("toast", 't')] 13 | public void GetTheMostFrequentCharacterShallWorkCorrectly(string input, char? expectedResult) 14 | { 15 | var result = Grouping.GetTheMostFrequentCharacter(input); 16 | Assert.AreEqual(expectedResult, result, $"The most frequent character in the word '{input}' is '{expectedResult}', but the result was '{result}'"); 17 | } 18 | 19 | [Test] 20 | public void EmptyString() 21 | { 22 | try 23 | { 24 | var result = Grouping.GetTheMostFrequentCharacter(""); 25 | Assert.AreEqual(null, result, $"The result shall be null for an empty input, but it was '{result}'"); 26 | } 27 | catch (Exception ex) 28 | { 29 | Assert.Fail($"The result shall be null for an empty input, but an expection was thrown. Exception message: {ex.Message}. (Did you possibly call the First method on an empty collection?)"); 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ExercisesTests/Grouping_Exercise2_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using System; 4 | using static ExercisesTests.Utilities.TestUtilities; 5 | using Pet = Exercises.Grouping.Pet; 6 | using PetType = Exercises.Grouping.PetType; 7 | 8 | namespace ExercisesTests 9 | { 10 | [TestFixture] 11 | public class Grouping_Exercise2_Tests 12 | { 13 | [Test] 14 | public void HeaviestPetTypeIsDog() 15 | { 16 | var pets = 17 | new[] 18 | { 19 | new Pet("Hannibal", PetType.Fish, 1.1f), 20 | new Pet("Anthony", PetType.Cat, 2f), 21 | new Pet("Ed", PetType.Cat, 0.7f), 22 | new Pet("Taiga", PetType.Dog, 35f), 23 | new Pet("Rex", PetType.Dog, 40f) 24 | }; 25 | 26 | var result = Grouping.FindTheHeaviestPetType(pets); 27 | var expectedResult = PetType.Dog; 28 | 29 | Assert.AreEqual(expectedResult, result, $"For pets {EnumerableToString(pets)} the result shall be {expectedResult} but it was {result}"); 30 | } 31 | 32 | [Test] 33 | public void HeaviestPetTypeIsCat() 34 | { 35 | var pets = 36 | new[] 37 | { 38 | new Pet("Shere Khan", PetType.Cat, 250f), 39 | new Pet("Alex", PetType.Cat, 200f), 40 | new Pet("Taiga", PetType.Dog, 35f), 41 | new Pet("Rex", PetType.Dog, 40f), 42 | new Pet("Lucky", PetType.Dog, 5f), 43 | new Pet("Bruce", PetType.Fish, 210f), 44 | }; 45 | 46 | var result = Grouping.FindTheHeaviestPetType(pets); 47 | var expectedResult = PetType.Cat; 48 | 49 | Assert.AreEqual(expectedResult, result, $"For pets {EnumerableToString(pets)} the result shall be {expectedResult} but it was {result}"); 50 | } 51 | 52 | [Test] 53 | public void EmptyPets() 54 | { 55 | try 56 | { 57 | var pets = 58 | new Pet[] 59 | { 60 | }; 61 | 62 | var result = Grouping.FindTheHeaviestPetType(pets); 63 | PetType? expectedResult = null; 64 | 65 | Assert.AreEqual(expectedResult, result, $"For empty pets collection the result shall be null but it was {result}"); 66 | } 67 | catch (Exception ex) 68 | { 69 | Assert.Fail($"The result shall be null for an empty input, but an expection was thrown. Exception message: {ex.Message}. (Did you possibly call the First or the Last methods on an empty collection?)"); 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /ExercisesTests/Grouping_RefactoringChallenge_Tests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using Exercises; 3 | using static ExercisesTests.Utilities.TestUtilities; 4 | 5 | namespace ExercisesTests 6 | { 7 | [TestFixture] 8 | public class Grouping_RefactoringChallenge_Tests 9 | { 10 | [Test] 11 | public void ShallCountPetsCorrectlyForNonEmptyInput() 12 | { 13 | var input = "Dog,Cat,Fish,Dog,Dog,Fish,Cat,Cat,Dog,Ferret,Dog"; 14 | var result = Grouping.CountPets(input); 15 | var expectedResult = new[] { "Dog:5", "Cat:3", "Fish:2", "Ferret:1" }; 16 | 17 | CollectionAssert.AreEqual(expectedResult, result, 18 | $"For INPUT '{input}' the RESULT shall be " + 19 | $"{EnumerableToString(expectedResult)} BUT IT WAS " + 20 | $"{EnumerableToString(result)}"); 21 | } 22 | 23 | [Test] 24 | public void EmptyInput() 25 | { 26 | var input = ""; 27 | var result = Grouping.CountPets(input); 28 | var expectedResult = new string[0]; 29 | 30 | CollectionAssert.AreEqual(expectedResult, result, 31 | $"For an EMPTY INPUT the RESULT shall be " + 32 | $"{EnumerableToString(expectedResult)} BUT IT WAS " + 33 | $"{EnumerableToString(result)}"); 34 | } 35 | 36 | [Test] 37 | public void ShallCountPetsCorrectlyForNonEmptyInput_Refactored() 38 | { 39 | var input = "Dog,Cat,Fish,Dog,Dog,Fish,Cat,Cat,Dog,Ferret,Dog"; 40 | var result = Grouping.CountPets_Refactored(input); 41 | var expectedResult = new[] { "Dog:5", "Cat:3", "Fish:2", "Ferret:1" }; 42 | 43 | CollectionAssert.AreEqual(expectedResult, result, 44 | $"For INPUT '{input}' the RESULT shall be " + 45 | $"{EnumerableToString(expectedResult)} BUT IT WAS " + 46 | $"{EnumerableToString(result)}"); 47 | } 48 | 49 | [Test] 50 | public void EmptyInput_Refactored() 51 | { 52 | var input = ""; 53 | var result = Grouping.CountPets_Refactored(input); 54 | var expectedResult = new string[0]; 55 | 56 | CollectionAssert.AreEqual(expectedResult, result, 57 | $"For an EMPTY INPUT the RESULT shall be " + 58 | $"{EnumerableToString(expectedResult)} BUT IT WAS " + 59 | $"{EnumerableToString(result)}"); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /ExercisesTests/IntersectExcept_Exercise1_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using static ExercisesTests.Utilities.TestUtilities; 4 | 5 | namespace ExercisesTests 6 | { 7 | [TestFixture] 8 | public class IntersectExcept_Exercise1_Tests 9 | { 10 | [Test] 11 | public void TwoCommonWords() 12 | { 13 | var words1 = new[] { "aaa", "BBB", "CCC" }; 14 | var words2 = new[] { "aaa", "ccc", "DDD" }; 15 | var expectedResult = 2; 16 | var result = IntersectExcept.CountCommonWords(words1, words2); 17 | 18 | Assert.AreEqual(expectedResult, result, $"For words1 {EnumerableToString(words1)} and words2 {EnumerableToString(words2)} the result shall be {expectedResult}, but it was {result}"); 19 | } 20 | 21 | [Test] 22 | public void ThreeCommonWords() 23 | { 24 | var words1 = new[] { "aaa", "BBB", "CCC", "FFF" }; 25 | var words2 = new[] { "aaa", "ccc", "DDD", "eee", "fFf", }; 26 | var expectedResult = 3; 27 | var result = IntersectExcept.CountCommonWords(words1, words2); 28 | 29 | Assert.AreEqual(expectedResult, result, $"For words1 {EnumerableToString(words1)} and words2 {EnumerableToString(words2)} the result shall be {expectedResult}, but it was {result}"); 30 | } 31 | 32 | [Test] 33 | public void EmptyCollections() 34 | { 35 | var words1 = new string[0]; 36 | var words2 = new string[0]; 37 | var expectedResult = 0; 38 | var result = IntersectExcept.CountCommonWords(words1, words2); 39 | 40 | Assert.AreEqual(expectedResult, result, $"For empty input collections the result shall be {expectedResult}, but it was {result}"); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /ExercisesTests/IntersectExcept_Exercise2_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using static ExercisesTests.Utilities.TestUtilities; 4 | 5 | namespace ExercisesTests 6 | { 7 | [TestFixture] 8 | public class IntersectExcept_Exercise2_Tests 9 | { 10 | [Test] 11 | public void SomeNumbersAreExclusive() 12 | { 13 | var numbers1 = new[] { 1, 2, 3, 4, 5, 6 }; 14 | var numbers2 = new[] { 9, 8, 7, 6, 5 }; 15 | var expectedResult = new int[] { 1, 2, 3, 4, 7, 8, 9 }; 16 | var result = IntersectExcept.GetExclusiveNumbers(numbers1, numbers2); 17 | 18 | Assert.AreEqual(expectedResult, result, $"For numbers1 {EnumerableToString(numbers1)} and numbers2 {EnumerableToString(numbers2)} the result shall be {EnumerableToString(expectedResult)}, but it was {EnumerableToString(result)}"); 19 | } 20 | 21 | [Test] 22 | public void AllNumbersAreExclusive() 23 | { 24 | var numbers1 = new[] { 40, 20 }; 25 | var numbers2 = new[] { 30, 10 }; 26 | var expectedResult = new int[] { 10, 20, 30, 40 }; 27 | var result = IntersectExcept.GetExclusiveNumbers(numbers1, numbers2); 28 | 29 | Assert.AreEqual(expectedResult, result, $"For numbers1 {EnumerableToString(numbers1)} and numbers2 {EnumerableToString(numbers2)} the result shall be {EnumerableToString(expectedResult)}, but it was {EnumerableToString(result)}"); 30 | } 31 | 32 | [Test] 33 | public void EmptyCollections() 34 | { 35 | var numbers1 = new int[0]; 36 | var numbers2 = new int[0]; 37 | var expectedResult = new int[0]; 38 | var result = IntersectExcept.GetExclusiveNumbers(numbers1, numbers2); 39 | 40 | Assert.AreEqual(expectedResult, result, $"For empty input collections the result shall be empty, but it was {EnumerableToString(result)}"); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /ExercisesTests/Join_RefactoringChallenge_Tests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using static ExercisesTests.Utilities.TestUtilities; 3 | using Person = Exercises.Join.Person; 4 | using House = Exercises.Join.House; 5 | using Exercises; 6 | using System.Collections.Generic; 7 | 8 | namespace ExercisesTests 9 | { 10 | [TestFixture] 11 | public class Join_RefactoringChallenge_Tests 12 | { 13 | [Test] 14 | public void GetHousesDataShallWorkProperly1() 15 | { 16 | var people = new Person[] 17 | { 18 | new Person(1, "John Smith"), 19 | new Person(2, "Stephanie Green"), 20 | new Person(3, "Martin Brown") 21 | }; 22 | 23 | var houses = new House[] 24 | { 25 | new House(2, "White Cottage, 18 Miners Overlook"), 26 | new House(3, "Hilltop Mansion, 234 Maple Road"), 27 | new House(3, "Beach Farm, 10 Seaside Street"), 28 | }; 29 | var result = Join.GetHousesData(people, houses); 30 | var expectedResult = new Dictionary 31 | { 32 | [houses[0]] = people[1], 33 | [houses[1]] = people[2], 34 | [houses[2]] = people[2], 35 | }; 36 | 37 | CollectionAssert.AreEquivalent(expectedResult, result, $"For PEOPLE {EnumerableToString(people)}, and HOUSES {EnumerableToString(houses)} the RESULT shall be {DictionaryToString(expectedResult)}, BUT IT WAS {DictionaryToString(result)}"); 38 | } 39 | 40 | [Test] 41 | public void GetHousesDataShallWorkProperly2() 42 | { 43 | var people = new Person[] 44 | { 45 | new Person(1, "John Smith"), 46 | new Person(2, "Stephanie Green"), 47 | new Person(3, "Martin Brown") 48 | }; 49 | 50 | var houses = new House[] 51 | { 52 | new House(2, "White Cottage"), 53 | new House(3, "Hilltop Mansion"), 54 | new House(3, "Beach Farm"), 55 | }; 56 | var result = Join.GetHousesData_Refactored(people, houses); 57 | var expectedResult = new Dictionary 58 | { 59 | [houses[0]] = people[1], 60 | [houses[1]] = people[2], 61 | [houses[2]] = people[2], 62 | }; 63 | 64 | CollectionAssert.AreEquivalent(expectedResult, result, $"For PEOPLE {EnumerableToString(people)}, and HOUSES {EnumerableToString(houses)} the RESULT shall be {DictionaryToString(expectedResult)}, BUT IT WAS {DictionaryToString(result)}"); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /ExercisesTests/MinMax_Exercise1_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | 4 | namespace ExercisesTests 5 | { 6 | [TestFixture] 7 | public class MinMax_Exercise1_Tests 8 | { 9 | [Test] 10 | public void ShortestWordHasLength1() 11 | { 12 | var words = new[] { "aaa", "bb", "c", "dddd" }; 13 | var wordsAsString = string.Join(", ", words); 14 | var result = MinMax.LengthOfTheShortestWord(words); 15 | Assert.NotNull(result, $"The test failed. The shortest word in the list " + 16 | $"({wordsAsString}) has a length of 1, but the result was null."); 17 | var message = $"The test failed. The shortest word in the list " + 18 | $"({wordsAsString}) has a length of 1, but the result was {result}."; 19 | Assert.AreEqual(1, result.Value, message); 20 | } 21 | 22 | [Test] 23 | public void ShortestWordHasLength2() 24 | { 25 | var words = new[] { "aaa", "bb", "ccc", "dddd" }; 26 | var wordsAsString = string.Join(", ", words); 27 | var result = MinMax.LengthOfTheShortestWord(words); 28 | Assert.NotNull(result, $"The test failed. The shortest word in the list " + 29 | $"({wordsAsString}) has a length of 2, but the result was null."); 30 | var message = $"The test failed. The shortest word in the list " + 31 | $"({wordsAsString}) has a length of 2, but the result was {result}."; 32 | Assert.AreEqual(2, result.Value, message); 33 | } 34 | 35 | [Test] 36 | public void EmptyCollection() 37 | { 38 | var words = new string[0]; 39 | var result = MinMax.LengthOfTheShortestWord(words); 40 | var message = $"The test failed. " + 41 | $"The result shall be null for an empty collection"; 42 | Assert.AreEqual(null, result, message); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /ExercisesTests/MinMax_Exercise2_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | 4 | namespace ExercisesTests 5 | { 6 | [TestFixture] 7 | public class MinMax_Exercise2_Tests 8 | { 9 | [Test] 10 | public void TwoLArgestNumbers() 11 | { 12 | var numbers = new[] { 3, 2, 2, 4, 4, 0 }; 13 | var numbersAsString = string.Join(", ", numbers); 14 | var result = MinMax.CountOfLargestNumbers(numbers); 15 | Assert.AreEqual(2, result, $"The test failed. " + 16 | $"The result for the list ({numbersAsString}) should be 2, but the result was {result}."); 17 | } 18 | 19 | [Test] 20 | public void OneLArgestNumber() 21 | { 22 | var numbers = new[] { 3, 2, 2, 4, 0 }; 23 | var numbersAsString = string.Join(", ", numbers); 24 | var result = MinMax.CountOfLargestNumbers(numbers); 25 | Assert.AreEqual(1, result, $"The test failed. " + 26 | $"The result for the list ({numbersAsString}) should be 1, but the result was {result}."); 27 | } 28 | 29 | [Test] 30 | public void EmptyCollectionTest() 31 | { 32 | var numbers = new int[0]; 33 | var result = MinMax.CountOfLargestNumbers(numbers); 34 | Assert.AreEqual(0, result, $"The test failed. " + 35 | $"The result for the empty list should be 0, but the result was {result}."); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /ExercisesTests/OfType_Exercise1_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using System.Collections.Generic; 4 | 5 | namespace ExercisesTests 6 | { 7 | [TestFixture] 8 | public class OfType_Exercise1_Tests 9 | { 10 | [Test] 11 | public void IntegerIsPresent() 12 | { 13 | var input = new object[] 14 | { 15 | null, 16 | "hello", 17 | 1, 18 | 2 19 | }; 20 | 21 | var result = OfType.GetTheFirstInteger(input); 22 | Assert.AreEqual(1, result, $"Expected result for input (null, 'hello', 1, 2) is 1, but was {result}"); 23 | } 24 | 25 | [Test] 26 | public void IntegerNotIsPresent() 27 | { 28 | var input = new object[] 29 | { 30 | null, 31 | "hello", 32 | new List() 33 | }; 34 | 35 | var result = OfType.GetTheFirstInteger(input); 36 | Assert.AreEqual(null, result, $"Expected result for input (null, 'hello', new List()) is null (because no integer is there), but was {result}"); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /ExercisesTests/OfType_Exercise2_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | 4 | namespace ExercisesTests 5 | { 6 | [TestFixture] 7 | public class OfType_Exercise2_Tests 8 | { 9 | [Test] 10 | public void AllStringAreUpperCase() 11 | { 12 | var input = new object[] 13 | { 14 | null, 15 | "HELLO", 16 | 1, 17 | "THERE" 18 | }; 19 | 20 | var result = OfType.AreAllStringsUpperCase(input); 21 | Assert.True(result, $"Expected result for input (null, 'HELLO', 1, 'THERE') is true, but was {result}"); 22 | } 23 | 24 | [Test] 25 | public void NotAllStringAreUpperCase() 26 | { 27 | var input = new object[] 28 | { 29 | null, 30 | "HELLO", 31 | 1, 32 | "there" 33 | }; 34 | 35 | var result = OfType.AreAllStringsUpperCase(input); 36 | Assert.False(result, $"Expected result for input (null, 'HELLO', 1, 'there') is false, but was {result}"); 37 | } 38 | 39 | [Test] 40 | public void NoStrings() 41 | { 42 | var input = new object[] 43 | { 44 | null, 45 | 1 46 | }; 47 | 48 | var result = OfType.AreAllStringsUpperCase(input); 49 | Assert.True(result, $"Expected result for input (null, 1) is true, but was {result}. If there is no string at all in this collection, the result should be true."); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /ExercisesTests/OrderBy_Exercise1_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | 4 | namespace ExercisesTests 5 | { 6 | [TestFixture] 7 | public class OrderBy_Exercise1_Tests 8 | { 9 | [Test] 10 | public void ShallOrderFromLongestToShortest() 11 | { 12 | var words = new[] { "bb", "a", "ccc" }; 13 | var result = OrderBy.OrderFromLongestToShortest(words); 14 | 15 | CollectionAssert.AreEqual(new[] { "ccc", "bb", "a" }, result); 16 | Assert.AreEqual("bb", words[0], "The order of the original collection should not be changed"); 17 | } 18 | 19 | [Test] 20 | public void ShallNotChangeAnything_IfAlreadyOrdered() 21 | { 22 | var words = new[] { "ccc", "bb", "a" }; 23 | var result = OrderBy.OrderFromLongestToShortest(words); 24 | 25 | CollectionAssert.AreEqual(new[] { "ccc", "bb", "a" }, result); 26 | Assert.AreEqual("ccc", words[0], "The order of the original collection should not be changed"); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ExercisesTests/OrderBy_Exercise2_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | 4 | namespace ExercisesTests 5 | { 6 | [TestFixture] 7 | public class OrderBy_Exercise2_Tests 8 | { 9 | [Test] 10 | public void EvenShallBeBeforeOdd1() 11 | { 12 | var numbers = new[] { 1, 2, 3, 4, 5, 6, 7 }; 13 | var expected = new[] { 6, 4, 2, 7, 5, 3, 1 }; 14 | var result = OrderBy.FirstEvenThenOddDescending(numbers); 15 | CollectionAssert.AreEqual(expected, result); 16 | } 17 | 18 | [Test] 19 | public void EvenShallBeBeforeOdd2() 20 | { 21 | var numbers = new[] { 1, 2, 3, 4 }; 22 | var expected = new[] { 4, 2, 3, 1 }; 23 | var result = OrderBy.FirstEvenThenOddDescending(numbers); 24 | CollectionAssert.AreEqual(expected, result); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ExercisesTests/OrderBy_QuerySyntax_Exercise1_Tests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using static ExercisesTests.Utilities.TestUtilities; 3 | using Exercises; 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | namespace ExercisesTests 8 | { 9 | [TestFixture] 10 | public class OrderBy_QuerySyntax_Exercise1_Tests 11 | { 12 | [Test] 13 | public void OrderFromLongestToShortestShallWorkCorrectly1() 14 | { 15 | var timespans = new List 16 | { 17 | TimeSpan.FromSeconds(93), 18 | TimeSpan.FromSeconds(10), 19 | TimeSpan.FromSeconds(16), 20 | TimeSpan.FromSeconds(71), 21 | }; 22 | 23 | var expectedResult = new List 24 | { 25 | TimeSpan.FromSeconds(93), 26 | TimeSpan.FromSeconds(71), 27 | TimeSpan.FromSeconds(16), 28 | TimeSpan.FromSeconds(10), 29 | }; 30 | 31 | var result = OrderByQuerySyntax.OrderFromLongestToShortest(timespans); 32 | 33 | CollectionAssert.AreEqual(expectedResult, result, $"For input " + 34 | $"{EnumerableToString(timespans)} the result shall be " + 35 | $"{EnumerableToString(expectedResult)} but it was " + 36 | $"'{EnumerableToString(result)}'"); 37 | } 38 | 39 | [Test] 40 | public void OrderFromLongestToShortestShallWorkCorrectly2() 41 | { 42 | var timespans = new List 43 | { 44 | TimeSpan.FromSeconds(93), 45 | TimeSpan.FromSeconds(5), 46 | TimeSpan.FromSeconds(16), 47 | }; 48 | 49 | var expectedResult = new List 50 | { 51 | TimeSpan.FromSeconds(93), 52 | TimeSpan.FromSeconds(16), 53 | TimeSpan.FromSeconds(5), 54 | }; 55 | 56 | var result = OrderByQuerySyntax.OrderFromLongestToShortest(timespans); 57 | 58 | CollectionAssert.AreEqual(expectedResult, result, 59 | $"For input {EnumerableToString(timespans)} the result shall be " + 60 | $"{EnumerableToString(expectedResult)} but it was " + 61 | $"'{EnumerableToString(result)}'"); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /ExercisesTests/OrderBy_QuerySyntax_Exercise2_Tests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using static ExercisesTests.Utilities.TestUtilities; 3 | using Exercises; 4 | using Point = Exercises.OrderByQuerySyntax.Point; 5 | 6 | namespace ExercisesTests 7 | { 8 | [TestFixture] 9 | public class OrderBy_QuerySyntax_Exercise2_Tests 10 | { 11 | [Test] 12 | public void OrderPointsShallWorkCorrectly1() 13 | { 14 | var points = new[] 15 | { 16 | new Point(10, 7), 17 | new Point(10, 5) , 18 | new Point(10, 6), 19 | new Point(7, 6) , 20 | new Point(11, 5) 21 | }; 22 | 23 | var expectedResult = new[] 24 | { 25 | new Point(7, 6) , 26 | new Point(10, 5) , 27 | new Point(10, 6), 28 | 29 | new Point(10, 7), 30 | new Point(11, 5) 31 | }; 32 | 33 | var result = OrderByQuerySyntax.OrderPoints(points); 34 | 35 | CollectionAssert.AreEqual(expectedResult, result, $"For input " + 36 | $"{EnumerableToString(points)} the result shall be " + 37 | $"{EnumerableToString(expectedResult)} but it was " + 38 | $"'{EnumerableToString(result)}'"); 39 | } 40 | 41 | [Test] 42 | public void OrderPointsShallWorkCorrectly2() 43 | { 44 | var points = new[] 45 | { 46 | new Point(10, 7), 47 | new Point(6, 5) , 48 | new Point(2, 6), 49 | }; 50 | 51 | var expectedResult = new[] 52 | { 53 | new Point(2, 6) , 54 | new Point(6, 5) , 55 | new Point(10, 7), 56 | }; 57 | 58 | var result = OrderByQuerySyntax.OrderPoints(points); 59 | 60 | CollectionAssert.AreEqual(expectedResult, result, 61 | $"For input {EnumerableToString(points)} the result shall be " + 62 | $"{EnumerableToString(expectedResult)} but it was " + 63 | $"'{EnumerableToString(result)}'"); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /ExercisesTests/OrderBy_RefactoringChallenge_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | namespace ExercisesTests 7 | { 8 | [TestFixture] 9 | public class OrderBy_RefactoringChallenge_Tests 10 | { 11 | [Test] 12 | public void OrderByMonth() 13 | { 14 | var dates = new List 15 | { 16 | new DateTime(2021, 4, 10), 17 | new DateTime(2020, 2, 8), 18 | new DateTime(2023, 6, 12), 19 | new DateTime(2025, 1, 16) 20 | }; 21 | 22 | var expected = new List 23 | { 24 | new DateTime(2025, 1, 16), 25 | new DateTime(2020, 2, 8), 26 | new DateTime(2021, 4, 10), 27 | new DateTime(2023, 6, 12), 28 | }; 29 | 30 | var result = OrderBy.OrderByMonth(dates); 31 | CollectionAssert.AreEqual(expected, result); 32 | } 33 | 34 | [Test] 35 | public void OrderByMonth_Refactored() 36 | { 37 | var dates = new List 38 | { 39 | new DateTime(2021, 4, 10), 40 | new DateTime(2020, 2, 8), 41 | new DateTime(2023, 6, 12), 42 | new DateTime(2025, 1, 16) 43 | }; 44 | 45 | var expected = new List 46 | { 47 | new DateTime(2025, 1, 16), 48 | new DateTime(2020, 2, 8), 49 | new DateTime(2021, 4, 10), 50 | new DateTime(2023, 6, 12), 51 | }; 52 | 53 | var result = OrderBy.OrderByMonth_Refactored(dates); 54 | CollectionAssert.AreEqual(expected, result); 55 | Assert.AreEqual(4, dates[0].Month, "Do not modify the input collection"); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /ExercisesTests/SelectMany_Exercise1_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using System.Collections.Generic; 4 | using static ExercisesTests.Utilities.TestUtilities; 5 | 6 | namespace ExercisesTests 7 | { 8 | [TestFixture] 9 | public class SelectMany_Exercise1_Tests 10 | { 11 | [Test] 12 | public void ShallBuildCartesianProductCorrectly() 13 | { 14 | var numbers = new HashSet { 1, 2, 5 }; 15 | 16 | var result = SelectMany.BuildCartesianProduct(numbers); 17 | 18 | var expectedResult = new[] 19 | { 20 | "1,1", "1,2", "1,5", "2,1", "2,2", "2,5", "5,1", "5,2", "5,5" 21 | }; 22 | 23 | CollectionAssert.AreEqual(expectedResult, result, 24 | $"For input (1,2,5) the result shall be " + 25 | $"{EnumerableToString(expectedResult)} but it was " + 26 | $"{EnumerableToString(result)}"); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ExercisesTests/SelectMany_Exercise2_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using static ExercisesTests.Utilities.TestUtilities; 4 | using Student = Exercises.SelectMany.Student; 5 | 6 | namespace ExercisesTests 7 | { 8 | [TestFixture] 9 | public class SelectMany_Exercise2_Tests 10 | { 11 | [Test] 12 | public void ShallBuildBestMarksAndStudentsCorrectly() 13 | { 14 | var students = new[] 15 | { 16 | new Student {Name = "Lucy", Marks = new [] {3,6,2,6}}, 17 | new Student {Name = "Tom", Marks = new [] {4,5}}, 18 | new Student {Name = "Alice", Marks = new [] {3,3,5}}, 19 | new Student {Name = "Brian", Marks = new [] {2,3,3}}, 20 | }; 21 | var result = SelectMany.BestMarksAndStudents(students); 22 | var expectedResult = new[] { 23 | "Lucy: 6", 24 | "Lucy: 6", 25 | "Alice: 5", 26 | "Tom: 5", 27 | "Tom: 4" 28 | }; 29 | 30 | CollectionAssert.AreEqual(expectedResult, result, $"For students {EnumerableToString(students)} the result shall be {EnumerableToString(expectedResult)} but it was {EnumerableToString(result)}"); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ExercisesTests/SelectMany_QuerySyntax_Exercise1_Tests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using static ExercisesTests.Utilities.TestUtilities; 3 | using Exercises; 4 | using Student = Exercises.SelectManyQuerySyntax.Student; 5 | 6 | namespace ExercisesTests 7 | { 8 | [TestFixture] 9 | public class SelectMany_QuerySyntax_Exercise1_Tests 10 | { 11 | [Test] 12 | public void GetStudentMarksInfoShallWorkCorrectly1() 13 | { 14 | var students = new[] 15 | { 16 | new Student {Name = "Jane Smith", Marks = new int[0]}, 17 | new Student {Name = "John Smith", Marks = new [] {6}}, 18 | new Student {Name = "Martin Brown", Marks = new [] {4,5}}, 19 | new Student {Name = "Amelia Green", Marks = new [] {2, 4, 4}}, 20 | }; 21 | 22 | var expectedResult = new[] 23 | { 24 | "Amelia Green: 2", 25 | "Amelia Green: 4", 26 | "Amelia Green: 4", 27 | "John Smith: 6", 28 | "Martin Brown: 4", 29 | "Martin Brown: 5", 30 | }; 31 | 32 | var result = SelectManyQuerySyntax.GetStudentMarksInfo(students); 33 | 34 | CollectionAssert.AreEqual(expectedResult, result, $"For INPUT {EnumerableToString(students)} the RESULT shall be '{EnumerableToString(expectedResult)}' BUT IT WAS '{EnumerableToString(result)}'"); 35 | } 36 | 37 | [Test] 38 | public void GetStudentMarksInfoShallWorkCorrectly2() 39 | { 40 | var students = new[] 41 | { 42 | new Student {Name = "Jane Smith", Marks = new [] {4,5}}, 43 | new Student {Name = "John Smith", Marks = new [] {6, 2}}, 44 | new Student {Name = "Martin Brown", Marks = null}, 45 | new Student {Name = "Amelia Green", Marks = new [] {2}}, 46 | }; 47 | 48 | var expectedResult = new[] 49 | { 50 | "Amelia Green: 2", 51 | "Jane Smith: 4", 52 | "Jane Smith: 5", 53 | "John Smith: 2", 54 | "John Smith: 6", 55 | }; 56 | 57 | var result = SelectManyQuerySyntax.GetStudentMarksInfo(students); 58 | 59 | CollectionAssert.AreEqual(expectedResult, result, $"For INPUT {EnumerableToString(students)} the RESULT shall be '{EnumerableToString(expectedResult)}' BUT IT WAS '{EnumerableToString(result)}'"); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /ExercisesTests/SelectMany_QuerySyntax_Exercise2_Tests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using static ExercisesTests.Utilities.TestUtilities; 3 | using Exercises; 4 | using System; 5 | 6 | namespace ExercisesTests 7 | { 8 | [TestFixture] 9 | public class SelectMany_QuerySyntax_Exercise2_Tests 10 | { 11 | [Test] 12 | public void SelectAllCombinationsWithSumBelow100ShallWorkCorrectly1() 13 | { 14 | var numbers1 = new[] 15 | { 16 | 1, 30, 42 17 | }; 18 | 19 | var numbers2 = new[] 20 | { 21 | 99, 82, 7 22 | }; 23 | 24 | var expectedResult = new[] 25 | { 26 | new Tuple(1,82), 27 | new Tuple(1,7), 28 | new Tuple(30, 7), 29 | new Tuple(42, 7), 30 | }; 31 | 32 | var result = SelectManyQuerySyntax.SelectAllCombinationsWithSumBelow100(numbers1, numbers2); 33 | 34 | CollectionAssert.AreEquivalent(expectedResult, result, $"For NUMBERS1 {EnumerableToString(numbers1)} and NUMBERS2 {EnumerableToString(numbers2)} the RESULT shall be '{EnumerableToString(expectedResult)}' BUT IT WAS '{EnumerableToString(result)}'"); 35 | } 36 | 37 | [Test] 38 | public void SelectAllCombinationsWithSumBelow100ShallWorkCorrectly2() 39 | { 40 | var numbers1 = new[] 41 | { 42 | 1, 60 43 | }; 44 | 45 | var numbers2 = new[] 46 | { 47 | 98, 82, 7 48 | }; 49 | 50 | var expectedResult = new[] 51 | { 52 | new Tuple(1,98), 53 | new Tuple(60, 7), 54 | new Tuple(1, 7), 55 | new Tuple(1, 82), 56 | }; 57 | 58 | var result = SelectManyQuerySyntax.SelectAllCombinationsWithSumBelow100(numbers1, numbers2); 59 | 60 | CollectionAssert.AreEquivalent(expectedResult, result, $"For NUMBERS1 {EnumerableToString(numbers1)} and NUMBERS2 {EnumerableToString(numbers2)} the RESULT shall be '{EnumerableToString(expectedResult)}' BUT IT WAS '{EnumerableToString(result)}'"); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /ExercisesTests/SelectQuerySyntax_Exercise1_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using static ExercisesTests.Utilities.TestUtilities; 4 | 5 | namespace ExercisesTests 6 | { 7 | [TestFixture] 8 | public class SelectQuerySyntax_Exercise1_Tests 9 | { 10 | [Test] 11 | public void GetAbsoluteValuesInfo_ShallWorkCorrectly1() 12 | { 13 | var numbers = new[] { 14 | -7, -3, 2, 8 15 | }; 16 | 17 | var expectedResult = new[] { 18 | "|-7|=7", 19 | "|-3|=3", 20 | "|2|=2", 21 | "|8|=8", 22 | }; 23 | 24 | var result = SelectQuerySyntax.GetAbsoluteValuesInfo(numbers); 25 | 26 | CollectionAssert.AreEqual(expectedResult, result, $"For INPUT {EnumerableToString(numbers)} the RESULT shall be '{EnumerableToString(expectedResult)}' BUT IT WAS '{EnumerableToString(result)}'"); 27 | } 28 | 29 | [Test] 30 | public void GetAbsoluteValuesInfo_ShallWorkCorrectly2() 31 | { 32 | var numbers = new[] { 33 | 4, -3, 2, 22, -95 34 | }; 35 | 36 | var expectedResult = new[] { 37 | "|4|=4", 38 | "|-3|=3", 39 | "|2|=2", 40 | "|22|=22", 41 | "|-95|=95", 42 | }; 43 | 44 | var result = SelectQuerySyntax.GetAbsoluteValuesInfo(numbers); 45 | 46 | CollectionAssert.AreEqual(expectedResult, result, $"For INPUT {EnumerableToString(numbers)} the RESULT shall be '{EnumerableToString(expectedResult)}' BUT IT WAS '{EnumerableToString(result)}'"); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /ExercisesTests/SelectQuerySyntax_Exercise2_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using static ExercisesTests.Utilities.TestUtilities; 4 | using House = Exercises.SelectQuerySyntax.House; 5 | 6 | namespace ExercisesTests 7 | { 8 | [TestFixture] 9 | public class SelectQuerySyntax_Exercise2_Tests 10 | { 11 | [Test] 12 | public void GetShortAddresses_ShallWorkCorrectly1() 13 | { 14 | var houses = new[] 15 | { 16 | new House("123 Old Road"), 17 | new House("Pelican Town, 2 Willow Lane, Stardew Valley Borough"), 18 | new House("Rocky Village, 22 Hill Road, Shadow Glen Borough"), 19 | }; 20 | 21 | var expectedResult = new[] { 22 | "123 Old Road", 23 | "2 Willow Lane", 24 | "22 Hill Road" 25 | }; 26 | 27 | var result = SelectQuerySyntax.GetShortAddresses(houses); 28 | 29 | CollectionAssert.AreEqual(expectedResult, result, 30 | $"For INPUT {EnumerableToString(houses)} the RESULT shall be " + 31 | $"'{EnumerableToString(expectedResult)}' BUT IT WAS " + 32 | $"'{EnumerableToString(result)}'"); 33 | } 34 | 35 | [Test] 36 | public void GetShortAddresses_ShallWorkCorrectly2() 37 | { 38 | var houses = new[] 39 | { 40 | new House("Maple Town, 123 Old Road, South Slope Borough"), 41 | new House("41 Beach Road"), 42 | new House("Oak Village, 12 Forest Alley, North Lake Borough"), 43 | new House("4 River Path"), 44 | }; 45 | 46 | var expectedResult = new[] { 47 | "123 Old Road", 48 | "41 Beach Road", 49 | "12 Forest Alley", 50 | "4 River Path", 51 | }; 52 | 53 | var result = SelectQuerySyntax.GetShortAddresses(houses); 54 | 55 | CollectionAssert.AreEqual(expectedResult, result, $"For INPUT " + 56 | $"{EnumerableToString(houses)} the RESULT shall be " + 57 | $"'{EnumerableToString(expectedResult)}' BUT IT WAS " + 58 | $"'{EnumerableToString(result)}'"); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /ExercisesTests/Select_Exercise1_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using System; 4 | using static ExercisesTests.Utilities.TestUtilities; 5 | namespace ExercisesTests 6 | { 7 | [TestFixture] 8 | public class Select_Exercise1_Tests 9 | { 10 | [Test] 11 | public void ShallGetAllNumbersAndTryParseStringsToInts() 12 | { 13 | var input = new object[] { "1", 3, "abc", new DateTime(2020, 1, 2), true, "10" }; 14 | 15 | var result = Select.GetNumbers(input); 16 | 17 | var expectedResult = new int[] { 1, 3, 10 }; 18 | 19 | CollectionAssert.AreEqual(expectedResult, result, $"For input collection " + 20 | $"{EnumerableToString(input)} the result shall be " + 21 | $"{EnumerableToString(expectedResult)} but it was " + 22 | $"{EnumerableToString(result)}"); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ExercisesTests/Select_Exercise2_Tests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using Exercises; 3 | using Person = Exercises.Select.Person; 4 | using System; 5 | using static ExercisesTests.Utilities.TestUtilities; 6 | 7 | namespace ExercisesTests 8 | { 9 | [TestFixture] 10 | public class Select_Exercise2_Tests 11 | { 12 | [Test] 13 | public void ShallParsePeopleDataCorrectly() 14 | { 15 | var input = "John Smith, 1983/08/21;Jane Doe, 1993/12/21;Francis Brown, invalid date here"; 16 | 17 | var result = Select.PeopleFromString(input); 18 | 19 | var expectedResult = new[] 20 | { 21 | new Person {FirstName = "John", LastName = "Smith", DateOfBirth = new DateTime(1983, 8, 21)}, 22 | new Person {FirstName = "Jane", LastName = "Doe", DateOfBirth = new DateTime(1993, 12, 21)} 23 | }; 24 | 25 | CollectionAssert.AreEqual(expectedResult, result, $"For input \"{input}\" " + 26 | $"the result shall be {EnumerableToString(expectedResult)} but it was " + 27 | $"{EnumerableToString(result)}"); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /ExercisesTests/Select_QuerySyntax_Exercise1_Tests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | 3 | namespace ExercisesTests 4 | { 5 | [TestFixture] 6 | public class Select_QuerySyntax_Exercise1_Tests 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /ExercisesTests/Select_QuerySyntax_Exercise2_Tests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | 3 | namespace ExercisesTests 4 | { 5 | [TestFixture] 6 | public class Select_QuerySyntax_Exercise2_Tests 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /ExercisesTests/Select_QuerySyntax_RefactoringChallenge_Tests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | 3 | namespace ExercisesTests 4 | { 5 | [TestFixture] 6 | public class Select_QuerySyntax_RefactoringChallenge_Tests 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /ExercisesTests/Select_RefactoringChallenge_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using System; 4 | 5 | namespace ExercisesTests 6 | { 7 | [TestFixture] 8 | public class Select_RefactoringChallenge_Tests 9 | { 10 | [Test] 11 | public void ShallGetTotalDurationOfSongsCorrectly() 12 | { 13 | var input = "4:12,2:43,3:51,4:29,3:24,3:14,4:46,3:25,4:52,3:27"; 14 | var result = Select.TotalDurationOfSongs(input); 15 | var expectedResult = new TimeSpan(0, 38, 23); 16 | 17 | Assert.AreEqual(expectedResult, result, $"For input \"{input}\" the " + 18 | $"result shall be {expectedResult} but it was {result}"); 19 | } 20 | 21 | [Test] 22 | public void ShallGetTotalDurationOfSongsCorrectly_Refactored() 23 | { 24 | var input = "4:12,2:43,3:51,4:29,3:24,3:14,4:46,3:25,4:52,3:27"; 25 | var result = Select.TotalDurationOfSongs_Refactored(input); 26 | var expectedResult = new TimeSpan(0, 38, 23); 27 | 28 | Assert.AreEqual(expectedResult, result, $"For input \"{input}\" the " + 29 | $"result shall be {expectedResult} but it was {result}"); 30 | } 31 | 32 | [Test] 33 | public void EmptyInput() 34 | { 35 | var input = ""; 36 | var result = Select.TotalDurationOfSongs(input); 37 | var expectedResult = new TimeSpan(); 38 | 39 | Assert.AreEqual(expectedResult, result, $"For an empty input the " + 40 | $"result shall be {expectedResult} but it was {result}"); 41 | } 42 | 43 | [Test] 44 | public void EmptyInput_Refactored() 45 | { 46 | var input = ""; 47 | var result = Select.TotalDurationOfSongs_Refactored(input); 48 | var expectedResult = new TimeSpan(); 49 | 50 | Assert.AreEqual(expectedResult, result, $"For an empty input the " + 51 | $"result shall be {expectedResult} but it was {result}"); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /ExercisesTests/Single_Exercise1_Tests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using System; 3 | using System.Collections.Generic; 4 | using Single = Exercises.Single; 5 | 6 | namespace ExercisesTests 7 | { 8 | [TestFixture] 9 | public class Single_Exercise1_Tests 10 | { 11 | [Test] 12 | public void SingleUppercaseWordIsPresent() 13 | { 14 | var words = new List { "aaa", "BBB", "CcC" }; 15 | var result = Single.GetTheOnlyUpperCaseWord(words); 16 | Assert.AreEqual("BBB", result, $"The only upper case word in (aaa, BBB, CcC) is BBB, but the result was {result}"); 17 | } 18 | 19 | [Test] 20 | public void NoUppercaseWordIsPresent() 21 | { 22 | var words = new List { "aaa", "bbB", "CcC" }; 23 | var result = Single.GetTheOnlyUpperCaseWord(words); 24 | Assert.AreEqual(null, result, $"No word in (aaa, bbB, CcC) is upper case, so the result should be null, but the result was {result}"); 25 | } 26 | 27 | [Test] 28 | public void MoreThanOneUppercaseWordIsPresent() 29 | { 30 | var words = new List { "aaa", "BBB", "CcC", "DDD" }; 31 | Assert.Throws(() => Single.GetTheOnlyUpperCaseWord(words), $"There two upper case words in (aaa, BBB, CcC, DDD) so an InvalidOperationException should be thrown"); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ExercisesTests/Single_Exercise2_Tests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using System; 3 | using System.Collections.Generic; 4 | using Single = Exercises.Single; 5 | 6 | namespace ExercisesTests 7 | { 8 | [TestFixture] 9 | public class Single_Exercise2_Tests 10 | { 11 | 12 | [Test] 13 | public void SingleElementCollectionIsPresent() 14 | { 15 | var input = new List> 16 | { 17 | new List {1,2,3}, 18 | new List {4}, 19 | new List {5,6} 20 | }; 21 | var result = Single.GetSingleElementCollection(input); 22 | Assert.AreEqual(input[1], result, $"There is one single-element collection (4) in collections (1,2,3), (4), (5,6)"); 23 | } 24 | 25 | [Test] 26 | public void MoreThanOneSingleElementCollectionIsPresent() 27 | { 28 | var input = new List> 29 | { 30 | new List {1,2,3}, 31 | new List {4}, 32 | new List {5,6}, 33 | new List {7}, 34 | }; 35 | Assert.Throws(() => Single.GetSingleElementCollection(input), $"There are more than one single-element collectiosn in collections (1,2,3), (4), (5,6), (7). InvalidOperationException was expected, but it was not thrown."); 36 | } 37 | 38 | [Test] 39 | public void SingleElementCollectionIsNotPresent() 40 | { 41 | var input = new List> 42 | { 43 | new List {1,2,3}, 44 | new List {5,6} 45 | }; 46 | Assert.Throws(() => Single.GetSingleElementCollection(input), $"There is no single-element collection in collections (1,2,3), (5,6). InvalidOperationException was expected, but it was not thrown."); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /ExercisesTests/Skip_Exercise1_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using Student = Exercises.Skip.Student; 4 | 5 | namespace ExercisesTests 6 | { 7 | [TestFixture] 8 | public class Skip_Exercise1_Tests 9 | { 10 | [Test] 11 | public void CalculateAverageMark() 12 | { 13 | var student = new Student 14 | { 15 | Marks = new int[] { 3, 4, 6, 6, 2, 5 } 16 | }; 17 | var result = Skip.CalculateAverageMark(student); 18 | Assert.AreEqual(4.5, result, $"For student with marks 3,4,6,6,2,5 result shall be 4.5"); 19 | } 20 | 21 | [Test] 22 | public void CalculateAverageMark_EmptyMarks() 23 | { 24 | var student = new Student 25 | { 26 | Marks = new int[] { } 27 | }; 28 | var result = Skip.CalculateAverageMark(student); 29 | Assert.AreEqual(0, result, $"For student with no marks result shall be 0"); 30 | } 31 | 32 | [Test] 33 | public void CalculateAverageMark_LessThan3Marks() 34 | { 35 | var student = new Student 36 | { 37 | Marks = new int[] { 2, 5 } 38 | }; 39 | var result = Skip.CalculateAverageMark(student); 40 | Assert.AreEqual(0, result, $"For student with less than 3 marks result shall be 0"); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /ExercisesTests/Sum_Exercise1_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using System.Collections.Generic; 4 | using static ExercisesTests.Utilities.TestUtilities; 5 | 6 | namespace ExercisesTests 7 | { 8 | [TestFixture] 9 | public class Sum_Exercise1_Tests 10 | { 11 | [Test] 12 | public void ForWordsLittleBrownFox_TheResultShallBe14() 13 | { 14 | var words = new List { "little", "brown", "fox" }; 15 | var result = Sum.TotalLength(words); 16 | var expectedResult = 14; 17 | Assert.AreEqual(expectedResult, result, 18 | $"For INPUT {EnumerableToString(words)} the RESULT shall be " + 19 | $"{expectedResult} but IT WAS {result}"); 20 | 21 | } 22 | 23 | [Test] 24 | public void ForEmptyWordsResultShallBeZero() 25 | { 26 | var words = new List { }; 27 | var result = Sum.TotalLength(words); 28 | var expectedResult = 0; 29 | Assert.AreEqual(expectedResult, result, 30 | $"For EMPTY INPUT the RESULT shall be {expectedResult} " + 31 | $"but IT WAS {result}"); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ExercisesTests/Sum_Exercise2_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using System.Collections.Generic; 4 | 5 | namespace ExercisesTests 6 | { 7 | [TestFixture] 8 | public class Sum_Exercise2_Tests 9 | { 10 | [Test] 11 | public void AverageSumShallWorkCorrectly() 12 | { 13 | var input = new List> 14 | { 15 | new List {1,2,3,2}, 16 | new List {1,5,6}, 17 | new List {2,2}, 18 | }; 19 | var result = Sum.AverageSum(input); 20 | var expectedResult = 8; 21 | Assert.AreEqual(expectedResult, result, 22 | $"For INPUT ((1,2,3,2),(1,5,6),(2,2)) the RESULT shall be " + 23 | $"{expectedResult} but IT WAS {result}"); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ExercisesTests/Take_Exercise2_Tests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using Pet = Exercises.Take.Pet; 3 | using Exercises; 4 | 5 | namespace ExercisesTests 6 | { 7 | [TestFixture] 8 | public class Take_Exercise2_Tests 9 | { 10 | [Test] 11 | public void FiftyPercent_ShallReturnHalfOfAllPets() 12 | { 13 | var pets = 14 | new[] 15 | { 16 | new Pet("Hannibal", 1.1f), 17 | new Pet("Anthony", 2f), 18 | new Pet("Ed", 0.7f), 19 | new Pet("Taiga", 35f), 20 | new Pet("Rex", 40f), 21 | new Pet("Lucky", 5f) 22 | }; 23 | 24 | var result = Take.GetGivenPercentOfHeaviestPets(pets, 50); 25 | var expectedResult = new[] { pets[3], pets[4], pets[5] }; 26 | CollectionAssert.AreEquivalent(expectedResult, result); 27 | } 28 | 29 | [Test] 30 | public void TwentyPercent_ShallReturnOneOfSixPets() 31 | { 32 | var pets = 33 | new[] 34 | { 35 | new Pet("Hannibal", 1.1f), 36 | new Pet("Anthony", 2f), 37 | new Pet("Ed", 0.7f), 38 | new Pet("Taiga", 35f), 39 | new Pet("Rex", 40f), 40 | new Pet("Lucky", 5f) 41 | }; 42 | 43 | var result = Take.GetGivenPercentOfHeaviestPets(pets, 20); 44 | var expectedResult = new[] { pets[4] }; 45 | CollectionAssert.AreEquivalent(expectedResult, result); 46 | } 47 | 48 | [Test] 49 | public void ThirtyPercent_ShallReturnOneOfFourPets() 50 | { 51 | var pets = 52 | new[] 53 | { 54 | new Pet("Hannibal", 50f), 55 | new Pet("Anthony", 5f), 56 | new Pet("Ed", 6f), 57 | new Pet("Taiga", 25f) 58 | }; 59 | 60 | var result = Take.GetGivenPercentOfHeaviestPets(pets, 30); 61 | var expectedResult = new[] { pets[0] }; 62 | CollectionAssert.AreEquivalent(expectedResult, result); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /ExercisesTests/Take_RefactoringChallenge_Tests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using System; 3 | using Exercises; 4 | using System.Linq; 5 | 6 | namespace ExercisesTests 7 | { 8 | [TestFixture] 9 | public class Take_RefactoringChallenge_Tests 10 | { 11 | [Test] 12 | public void GetDatesBeforeXXCentury_ShallWorkCorrectly() 13 | { 14 | var dates = new[] 15 | { 16 | new DateTime(1741, 1, 1), 17 | new DateTime(1899, 1, 1), 18 | new DateTime(1900, 1, 1), 19 | new DateTime(1901, 1, 1), 20 | new DateTime(1451, 1, 1) 21 | }; 22 | 23 | var expectedResult = new[] 24 | { 25 | new DateTime(1741, 1, 1), 26 | new DateTime(1899, 1, 1), 27 | new DateTime(1900, 1, 1) 28 | }; 29 | 30 | var result = Take.GetDatesBeforeXXCentury(dates); 31 | var datesAsString = string.Join(", ", dates.Select(d => d.ToString("dd/MM/yyyy"))); 32 | var expectedResultAsString = string.Join(", ", expectedResult.Select(d => d.ToString("dd/MM/yyyy"))); 33 | var resultAsString = string.Join(", ", result.Select(d => d.ToString("dd/MM/yyyy"))); 34 | CollectionAssert.AreEqual(expectedResult, result, $"Input dates: ({datesAsString}), expected result: ({expectedResultAsString}), actual result: ({resultAsString})"); 35 | } 36 | 37 | [Test] 38 | public void GetDatesBeforeXXCentury_Refactored_ShallWorkCorrectly() 39 | { 40 | var dates = new[] 41 | { 42 | new DateTime(1741, 1, 1), 43 | new DateTime(1899, 1, 1), 44 | new DateTime(1900, 1, 1), 45 | new DateTime(1901, 1, 1), 46 | new DateTime(1451, 1, 1) 47 | }; 48 | 49 | var expectedResult = new[] 50 | { 51 | new DateTime(1741, 1, 1), 52 | new DateTime(1899, 1, 1), 53 | new DateTime(1900, 1, 1) 54 | }; 55 | 56 | var result = Take.GetDatesBeforeXXCentury_Refactored(dates); 57 | var datesAsString = string.Join(", ", dates.Select(d => d.ToString("dd/MM/yyyy"))); 58 | var expectedResultAsString = string.Join(", ", expectedResult.Select(d => d.ToString("dd/MM/yyyy"))); 59 | var resultAsString = string.Join(", ", result.Select(d => d.ToString("dd/MM/yyyy"))); 60 | CollectionAssert.AreEqual(expectedResult, result, $"Input dates: ({datesAsString}), expected result: ({expectedResultAsString}), actual result: ({resultAsString})"); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /ExercisesTests/Utilities/TestUtilities.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace ExercisesTests.Utilities 5 | { 6 | public static class TestUtilities 7 | { 8 | public static string EnumerableToString( 9 | IEnumerable input, string separator = ", ") 10 | { 11 | return $"({string.Join(separator, input)})"; 12 | } 13 | 14 | public static string DictionaryToString(Dictionary input) 15 | { 16 | var str = string.Join(", ", input.Select(kv => KeyValuePairToString(kv))); 17 | return $"({str})"; 18 | } 19 | 20 | public static string KeyValuePairToString(KeyValuePair kv) 21 | { 22 | var value = kv.Value == null ? "null" : kv.Value.ToString(); 23 | return $"({kv.Key}:{value})"; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ExercisesTests/Where_Exercise2_Tests.cs: -------------------------------------------------------------------------------- 1 | using Exercises; 2 | using NUnit.Framework; 3 | using System.Linq; 4 | 5 | namespace ExercisesTests 6 | { 7 | [TestFixture] 8 | public class Where_Exercise2_Tests 9 | { 10 | [Test] 11 | public void ShallExcludeNonNumberedWord() 12 | { 13 | var words = new[] { "1.AAA", "2.BBB", "invalidWord", "4.DDD" }; 14 | var expectedWords = new[] { "1.AAA", "2.BBB", "4.DDD" }; 15 | var expectedResultAsString = string.Join(", ", expectedWords); 16 | 17 | var wordsAsString = string.Join(", ", words); 18 | var result = Where.GetProperlyIndexedWords(words); 19 | var resultAsString = result.Any() ? string.Join(", ", result) : "empty"; 20 | Assert.AreEqual(expectedWords, result, $"The input collection was: {wordsAsString}, the result was {resultAsString}, expectedResult is: {expectedResultAsString}"); 21 | } 22 | 23 | [Test] 24 | public void ShallExcludeWordsAfterMissingIndex() 25 | { 26 | var words = new[] { "1.AAA", "2.BBB", "4.DDD" }; 27 | var expectedWords = new[] { "1.AAA", "2.BBB" }; 28 | var expectedResultAsString = string.Join(", ", expectedWords); 29 | 30 | var wordsAsString = string.Join(", ", words); 31 | var result = Where.GetProperlyIndexedWords(words); 32 | var resultAsString = result.Any() ? string.Join(", ", result) : "empty"; 33 | Assert.AreEqual(expectedWords, result, $"The input collection was: {wordsAsString}, the result was {resultAsString}, expectedResult is: {expectedResultAsString}"); 34 | } 35 | 36 | [Test] 37 | public void ShallIncludeOneWord_IfOtherInvalidOrWronglyIndexed() 38 | { 39 | var words = new[] { "0.AAA", "2.BBB", "invalidWord", "5.DDD" }; 40 | var expectedWords = new[] { "2.BBB" }; 41 | var expectedResultAsString = string.Join(", ", expectedWords); 42 | 43 | var wordsAsString = string.Join(", ", words); 44 | var result = Where.GetProperlyIndexedWords(words); 45 | var resultAsString = result.Any() ? string.Join(", ", result) : "empty"; 46 | Assert.AreEqual(expectedWords, result, $"The input collection was: {wordsAsString}, the result was {resultAsString}, expectedResult is: {expectedResultAsString}"); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /ExercisesTests/Where_QuerySyntax_Exercise1_Tests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using static ExercisesTests.Utilities.TestUtilities; 3 | using Exercises; 4 | using System; 5 | using System.Collections.Generic; 6 | using Person = Exercises.WhereQuerySyntax.Person; 7 | 8 | namespace ExercisesTests 9 | { 10 | [TestFixture] 11 | public class Where_QuerySyntax_Exercise1_Tests 12 | { 13 | [Test] 14 | public void GetBornAfter1952ShallGetOnlyBornAfter1950() 15 | { 16 | var people = new List 17 | { 18 | new Person("Geraldine Smith", new DateTime(1920, 12, 2) ), 19 | new Person("John Smith", new DateTime(1950, 4, 8)) , 20 | new Person("Monica Smith", new DateTime(1954,11, 3)) , 21 | new Person("Jake Smith", new DateTime(1982, 8, 3) ) 22 | }; 23 | 24 | var expectedResult = new List 25 | { 26 | new Person("Monica Smith", new DateTime(1954, 11, 3) ), 27 | new Person("Jake Smith", new DateTime(1982, 8, 3) ) 28 | }; 29 | 30 | var result = WhereQuerySyntax.GetBornAfter(1950, people); 31 | 32 | CollectionAssert.AreEqual(expectedResult, result, $"For input {EnumerableToString(people)} the result shall be {EnumerableToString(expectedResult)} but it was '{EnumerableToString(result)}'"); 33 | } 34 | 35 | [Test] 36 | public void GetBornAfter1980ShallGetOnlyBornAfter1980() 37 | { 38 | var people = new List 39 | { 40 | new Person("Geraldine Smith", new DateTime(1920, 12, 2) ), 41 | new Person("John Smith", new DateTime(1950, 4, 8)) , 42 | new Person("Monica Smith", new DateTime(1954,11, 3)) , 43 | new Person("Jake Smith", new DateTime(1982, 8, 3) ) 44 | }; 45 | 46 | var expectedResult = new List 47 | { 48 | new Person("Jake Smith", new DateTime(1982, 8, 3) ) 49 | }; 50 | 51 | var result = WhereQuerySyntax.GetBornAfter(1980, people); 52 | 53 | CollectionAssert.AreEqual(expectedResult, result, $"For input {EnumerableToString(people)} the result shall be {EnumerableToString(expectedResult)} but it was '{EnumerableToString(result)}'"); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /ExercisesTests/Where_QuerySyntax_Exercise2_Tests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using static ExercisesTests.Utilities.TestUtilities; 3 | using Exercises; 4 | using System.Collections.Generic; 5 | using Student = Exercises.WhereQuerySyntax.Student; 6 | 7 | namespace ExercisesTests 8 | { 9 | [TestFixture] 10 | public class Where_QuerySyntax_Exercise2_Tests 11 | { 12 | [Test] 13 | public void GetStudentsWhoNeedToStudyMoreShallWorkCorrectly1() 14 | { 15 | var students = new List 16 | { 17 | new Student {Name = "Stacey Brown", Marks = new int[0]}, 18 | new Student {Name = "Jake Smith", Marks = new int[] {3, 5, 5}}, 19 | new Student {Name = "Chris Miller", Marks = new int[]{2,3}}, 20 | new Student {Name = "Anne Evans", Marks = new int[]{3, 3, 1}}, 21 | }; 22 | 23 | var expectedResult = new List 24 | { 25 | new Student {Name = "Stacey Brown", Marks = new int[0]}, 26 | new Student {Name = "Chris Miller", Marks = new int[]{2,3}}, 27 | new Student {Name = "Anne Evans", Marks = new int[]{3, 3, 1}}, 28 | }; 29 | 30 | var result = WhereQuerySyntax.GetStudentsWhoNeedToStudyMore(students); 31 | 32 | CollectionAssert.AreEqual(expectedResult, result, $"For INPUT {EnumerableToString(students)} the RESULT shall be {EnumerableToString(expectedResult)} but IT WAS '{EnumerableToString(result)}'"); 33 | } 34 | 35 | [Test] 36 | public void GetStudentsWhoNeedToStudyMoreShallWorkCorrectly2() 37 | { 38 | var students = new List 39 | { 40 | new Student {Name = "Jake Smith", Marks = new int[] {3, 5}}, 41 | new Student {Name = "Chris Miller", Marks = new int[]{3,3}}, 42 | }; 43 | 44 | var expectedResult = new List 45 | { 46 | }; 47 | 48 | var result = WhereQuerySyntax.GetStudentsWhoNeedToStudyMore(students); 49 | 50 | CollectionAssert.AreEqual(expectedResult, result, $"For input {EnumerableToString(students)} the result shall be empty but it was '{EnumerableToString(result)}'"); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /ExercisesTests/Zip_Exercise1_Tests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using static ExercisesTests.Utilities.TestUtilities; 3 | using Exercises; 4 | using System; 5 | 6 | namespace ExercisesTests 7 | { 8 | [TestFixture] 9 | public class Zip_Exercise1_Tests 10 | { 11 | [Test] 12 | public void BuildDatesShallWorkCorrectly1() 13 | { 14 | var years = new[] { 2020, 1990, 2010 }; 15 | var months = new[] { 3, 5, 1 }; 16 | var days = new[] { 1, 5, 17 }; 17 | var result = Zip.BuildDates(years, months, days); 18 | var expectedResult = new[] { new DateTime(1990, 5, 5), new DateTime(2010, 1, 17), new DateTime(2020, 3, 1) }; 19 | 20 | Assert.AreEqual(expectedResult, result, $"For years " + 21 | $"{EnumerableToString(years)}, months {EnumerableToString(months)} " + 22 | $"and days {EnumerableToString(days)} the result shall be" + 23 | $" {EnumerableToString(expectedResult)} but it was " + 24 | $"'{EnumerableToString(result)}'"); 25 | } 26 | 27 | [Test] 28 | public void BuildDatesShallWorkCorrectly2() 29 | { 30 | var years = new[] { 1564, 1891 }; 31 | var months = new[] { 2, 12 }; 32 | var days = new[] { 9, 10 }; 33 | var result = Zip.BuildDates(years, months, days); 34 | var expectedResult = new[] { new DateTime(1564, 2, 9), new DateTime(1891, 12, 10) }; 35 | 36 | Assert.AreEqual(expectedResult, result, $"For years " + 37 | $"{EnumerableToString(years)}, months {EnumerableToString(months)} " + 38 | $"and days {EnumerableToString(days)} the result shall be " + 39 | $"{EnumerableToString(expectedResult)} but it was " + 40 | $"'{EnumerableToString(result)}'"); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /ExercisesTests/Zip_RefactoringChallenge_Tests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using static ExercisesTests.Utilities.TestUtilities; 3 | using Exercises; 4 | 5 | namespace ExercisesTests 6 | { 7 | [TestFixture] 8 | public class Zip_RefactoringChallenge_Tests 9 | { 10 | [Test] 11 | public void MakeListShallWorkCorrectly1() 12 | { 13 | var words = new[] { "a", "little", "duck", "swims", "in", "a", "pond" }; 14 | 15 | var result = Zip.MakeList(words); 16 | var expectedResult = new[] { 17 | "A) a", 18 | "B) little", 19 | "C) duck", 20 | "D) swims", 21 | "E) in", 22 | "F) a", 23 | "G) pond" 24 | }; 25 | 26 | CollectionAssert.AreEqual(expectedResult, result, $"For words {EnumerableToString(words)} the result shall be {EnumerableToString(expectedResult)} but it was '{EnumerableToString(result)}'"); 27 | } 28 | 29 | [Test] 30 | public void MakeListShallWorkCorrectly2() 31 | { 32 | var words = new[] { "duck" }; 33 | 34 | var result = Zip.MakeList(words); 35 | var expectedResult = new[] { 36 | "A) duck" 37 | }; 38 | 39 | CollectionAssert.AreEqual(expectedResult, result, $"For words {EnumerableToString(words)} the result shall be {EnumerableToString(expectedResult)} but it was '{EnumerableToString(result)}'"); 40 | } 41 | 42 | [Test] 43 | public void MakeListShallWorkCorrectly1_Refactored() 44 | { 45 | var words = new[] { "a", "little", "duck", "swims", "in", "a", "pond" }; 46 | 47 | var result = Zip.MakeList_Refactored(words); 48 | var expectedResult = new[] { 49 | "A) a", 50 | "B) little", 51 | "C) duck", 52 | "D) swims", 53 | "E) in", 54 | "F) a", 55 | "G) pond" 56 | }; 57 | 58 | CollectionAssert.AreEqual(expectedResult, result, $"For words {EnumerableToString(words)} the result shall be {EnumerableToString(expectedResult)} but it was '{EnumerableToString(result)}'"); 59 | } 60 | 61 | [Test] 62 | public void MakeListShallWorkCorrectly2_Refactored() 63 | { 64 | var words = new[] { "duck" }; 65 | 66 | var result = Zip.MakeList_Refactored(words); 67 | var expectedResult = new[] { 68 | "A) duck" 69 | }; 70 | 71 | CollectionAssert.AreEqual(expectedResult, result, $"For words {EnumerableToString(words)} the result shall be {EnumerableToString(expectedResult)} but it was '{EnumerableToString(result)}'"); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /LinqTutorial/Data/Data.cs: -------------------------------------------------------------------------------- 1 | using LinqTutorial.DataTypes; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | namespace LinqTutorial 7 | { 8 | public static class Data 9 | { 10 | public static IEnumerable Pets = 11 | new[] 12 | { 13 | new Pet(1, "Hannibal", PetType.Fish, 1.1f), 14 | new Pet(2, "Anthony", PetType.Cat, 2f), 15 | new Pet(3, "Ed", PetType.Cat, 0.7f), 16 | new Pet(4, "Taiga", PetType.Dog, 35f), 17 | new Pet(5, "Rex", PetType.Dog, 40f), 18 | new Pet(6, "Lucky", PetType.Dog, 5f), 19 | new Pet(7, "Storm", PetType.Cat, 0.9f), 20 | new Pet(8, "Nyan", PetType.Cat, 2.2f) 21 | }; 22 | 23 | public static IEnumerable VeterinaryClinicAppointments = 24 | new[] 25 | { 26 | new VeterinaryClinicAppointment(clinicId:2, petId:1, new DateTime(2021, 10, 1, 12, 0, 0)), 27 | new VeterinaryClinicAppointment(clinicId:3, petId:3, new DateTime(2021, 10, 1, 12, 30, 0)), 28 | new VeterinaryClinicAppointment(clinicId:1, petId:4, new DateTime(2021, 10, 2, 13, 30, 0)), 29 | new VeterinaryClinicAppointment(clinicId:2, petId:1, new DateTime(2021, 11, 1, 12, 0, 0)) 30 | }; 31 | 32 | public static IEnumerable VeterinaryClinics = new[] 33 | { 34 | new VeterinaryClinic(id: 1, name: "Happy Paws Clinic"), 35 | new VeterinaryClinic(id: 2, name: "Fish Doctor"), 36 | new VeterinaryClinic(id: 3, name: "Pure Purr Clinic") 37 | }; 38 | 39 | 40 | public static IEnumerable People = 41 | new[] 42 | { 43 | new PetOwner(1, "John", new [] { 44 | Pets.ElementAt(0), 45 | Pets.ElementAt(1), 46 | }), 47 | new PetOwner(2, "Jack", new [] { 48 | Pets.ElementAt(2) 49 | }), 50 | new PetOwner(3, "Stephanie", new [] { 51 | Pets.ElementAt(3), 52 | Pets.ElementAt(4), 53 | Pets.ElementAt(5) 54 | }) 55 | }; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /LinqTutorial/DataTypes/Pet.cs: -------------------------------------------------------------------------------- 1 | namespace LinqTutorial.DataTypes 2 | { 3 | public class Pet 4 | { 5 | public int Id { get; } 6 | public string Name { get; } 7 | public PetType PetType { get; } 8 | public float Weight { get; } 9 | 10 | public Pet(int id, string name, PetType petType, float weight) 11 | { 12 | Id = id; 13 | Name = name; 14 | PetType = petType; 15 | Weight = weight; 16 | } 17 | 18 | public override string ToString() 19 | { 20 | return $"Id: {Id}, Name: {Name}, Type: {PetType}, Weight: {Weight}"; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /LinqTutorial/DataTypes/PetEqualityByIdComparer.cs: -------------------------------------------------------------------------------- 1 | using LinqTutorial.DataTypes; 2 | using System.Collections.Generic; 3 | using System.Diagnostics.CodeAnalysis; 4 | 5 | namespace LinqTutorial 6 | { 7 | internal class PetEqualityByIdComparer : IEqualityComparer 8 | { 9 | public bool Equals(Pet x, Pet y) 10 | { 11 | return x.Id == y.Id; 12 | } 13 | 14 | public int GetHashCode([DisallowNull] Pet pet) 15 | { 16 | return pet.Id; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /LinqTutorial/DataTypes/PetOwner.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace LinqTutorial.DataTypes 4 | { 5 | public class PetOwner 6 | { 7 | public int Id { get; } 8 | public string Name { get; } 9 | public IEnumerable Pets; 10 | 11 | public PetOwner(int id, string name, IEnumerable pets) 12 | { 13 | Id = id; 14 | Name = name; 15 | Pets = pets; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /LinqTutorial/DataTypes/PetType.cs: -------------------------------------------------------------------------------- 1 | namespace LinqTutorial.DataTypes 2 | { 3 | public enum PetType 4 | { 5 | Cat, 6 | Dog, 7 | Fish 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /LinqTutorial/DataTypes/VeterinaryClinic.cs: -------------------------------------------------------------------------------- 1 | namespace LinqTutorial.DataTypes 2 | { 3 | public class VeterinaryClinic 4 | { 5 | public int Id { get; set; } 6 | public string Name { get; } 7 | 8 | public VeterinaryClinic(int id, string name) 9 | { 10 | Id = id; 11 | Name = name; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /LinqTutorial/DataTypes/VeterinaryClinicAppointment.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace LinqTutorial.DataTypes 4 | { 5 | public class VeterinaryClinicAppointment 6 | { 7 | public int ClinicId { get; set; } 8 | public int PetId { get; } 9 | public DateTime Date { get; } 10 | 11 | public VeterinaryClinicAppointment(int clinicId, int petId, DateTime date) 12 | { 13 | ClinicId = clinicId; 14 | PetId = petId; 15 | Date = date; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /LinqTutorial/Examples/All.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using LinqTutorial.DataTypes; 4 | 5 | namespace LinqTutorial 6 | { 7 | static class All 8 | { 9 | //System.Linq.Enumerable.All 10 | public static void Run() 11 | { 12 | var numbers = new[] { 10, 1, 4, 17, 122 }; 13 | 14 | //All is used to check if all elements in the collection meet the specific criteria 15 | var areAllNumbersLargerThanZero = numbers.All(n => n > 0); 16 | Console.WriteLine($"areAllNumbersLargerThanZero: {areAllNumbersLargerThanZero}"); 17 | 18 | var doAllPetsHaveNonEmptyName = Data.Pets.All(pet => !string.IsNullOrEmpty(pet.Name)); 19 | Console.WriteLine($"doAllPetsHaveNonEmptyName: {doAllPetsHaveNonEmptyName}"); 20 | 21 | var areAllPetsCats = Data.Pets.All(pet => pet.PetType == PetType.Cat); 22 | Console.WriteLine($"areAllPetsCats: {areAllPetsCats}"); 23 | 24 | //please note that we can achieve the same result by using Any 25 | //and reversing the condition 26 | var doAllPetsHaveNonEmptyName_WithAny = 27 | !(Data.Pets.Any(pet => string.IsNullOrEmpty(pet.Name))); //note the "!" 28 | Console.WriteLine($"doAllPetsHaveNonEmptyName_WithAny: {doAllPetsHaveNonEmptyName_WithAny}"); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /LinqTutorial/Examples/Any.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System; 3 | 4 | namespace LinqTutorial.MethodSyntax 5 | { 6 | static class Any 7 | { 8 | //System.Linq.Enumerable.Any 9 | public static void Run() 10 | { 11 | var numbers = new[] { 10, 1, 4, 17, 122 }; 12 | 13 | //Any is used to check if any element in the collection meets the given criteria 14 | var isAnyNumberLargerThan100 = numbers.Any(n => n > 100); 15 | Console.WriteLine($"isAnyNumberLargerThan100: {isAnyNumberLargerThan100}"); 16 | 17 | var isAnyPetNamedBruce = Data.Pets.Any(pet => pet.Name == "Bruce"); 18 | Console.WriteLine($"isAnyPetNamedBruce: {isAnyPetNamedBruce}"); 19 | 20 | var isAnyPetNamedHannibal = Data.Pets.Any(pet => pet.Name == "Hannibal"); 21 | Console.WriteLine($"isAnyPetNamedHannibal: {isAnyPetNamedHannibal}"); 22 | 23 | //we can of course use more complex conditions 24 | //for example, to check if there is any pet with an even Id 25 | //and name longer than 6 letters 26 | var isThereASpecificPet = Data.Pets.Any( 27 | pet => pet.Name.Length > 6 && pet.Id % 2 == 0); 28 | Console.WriteLine($"isThereASpecificPet: {isThereASpecificPet}"); 29 | 30 | //we can use Any without parameter to check if the collection is not empty: 31 | var isNotEmpty = Data.Pets.Any(); 32 | Console.WriteLine($"isNotEmpty: {isNotEmpty}"); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /LinqTutorial/Examples/Average.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace LinqTutorial 5 | { 6 | static class Average 7 | { 8 | //System.Linq.Enumerable.Average 9 | public static void Run() 10 | { 11 | var numbers = new[] { 10, 1, 4, 17, 122 }; 12 | 13 | //Average calculates the average of the values 14 | var averageOfNumbers = numbers.Average(); 15 | Console.WriteLine($"averageOfNumbers: {averageOfNumbers}"); 16 | 17 | var averagePetWeight = Data.Pets.Average(pet => pet.Weight); 18 | Console.WriteLine($"averagePetWeight: {averagePetWeight}"); 19 | 20 | //Average only works for numbers 21 | //so the below will not work 22 | //var averagePet = Data.Pets.Average(); 23 | 24 | //if the collection is empty, Average will throw an exception 25 | //var emptyNumbers = new int[0]; 26 | //var emptyCollectionAverage = emptyNumbers.Average(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /LinqTutorial/Examples/Contains.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using LinqTutorial.DataTypes; 5 | 6 | namespace LinqTutorial 7 | { 8 | static class Contains 9 | { 10 | //System.Linq.Enumerable.Contains 11 | public static void Run() 12 | { 13 | var numbers = new[] { 10, 1, 4, 17, 122 }; 14 | 15 | //Contains checks if given element is present in the collection 16 | var contains10 = numbers.Contains(10); 17 | Console.WriteLine($"contains10: {contains10}"); 18 | 19 | var contains11 = numbers.Contains(11); 20 | Console.WriteLine($"contains11: {contains11}"); 21 | 22 | //the below will return false, because pets are compares by reference 23 | //and we create a new reference here 24 | var containsAnthony = Data.Pets.Contains(new Pet(2, "Anthony", PetType.Cat, 2f)); 25 | Console.WriteLine($"containsAnthony: {containsAnthony}"); 26 | 27 | //let's store the reference to Hannibal pet 28 | var hannibal = Data.Pets.First(); //selects the first element in the collection 29 | var containsHannibal = Data.Pets.Contains(hannibal); 30 | Console.WriteLine($"containsHannibal: {containsHannibal}"); 31 | 32 | //we can use any EqualityComparer we like 33 | var containsAnthonyWithEqualityComparer = Data.Pets.Contains( 34 | new Pet(2, "Anthony", PetType.Cat, 2f), new PetEqualityByIdComparer()); 35 | Console.WriteLine($"containsAnthonyWithEqualityComparer: " + 36 | $"{containsAnthonyWithEqualityComparer}"); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /LinqTutorial/Examples/Count.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using LinqTutorial.DataTypes; 4 | 5 | namespace LinqTutorial 6 | { 7 | static class Count 8 | { 9 | //System.Linq.Enumerable.Count 10 | //System.Linq.Enumerable.LongCount 11 | public static void Run() 12 | { 13 | //Count returns the number of element that meet the specific criteria 14 | var countOfDogs = Data.Pets.Count(pet => pet.PetType == PetType.Dog); 15 | Console.WriteLine($"countOfDogs: {countOfDogs}"); 16 | 17 | //LongCount dos the same, but returns long instead of int 18 | //We should this method rather than Count 19 | //when we expect the result to be greater than int.MaxValue (2147483647) 20 | var countOfPetsNamedBruce = Data.Pets.LongCount(pet => pet.Name == "Bruce"); 21 | Console.WriteLine($"countOfPetsNamedBruce: {countOfPetsNamedBruce}"); 22 | 23 | //we can, of course, define more complex predicate 24 | var countOfAllSmallDogs = Data.Pets.Count(pet => 25 | pet.PetType == PetType.Dog && 26 | pet.Weight < 10); 27 | Console.WriteLine($"countOfAllSmallDogs: {countOfAllSmallDogs}"); 28 | 29 | //count of all elements 30 | var countOfAllElements = Data.Pets.Count(); 31 | Console.WriteLine($"countOfAllElements: {countOfAllElements}"); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /LinqTutorial/Examples/Distinct.cs: -------------------------------------------------------------------------------- 1 | using LinqTutorial.DataTypes; 2 | using System.Linq; 3 | using Utilities; 4 | 5 | namespace LinqTutorial 6 | { 7 | static class Distinct 8 | { 9 | //System.Linq.Enumerable.Distinct 10 | public static void Run() 11 | { 12 | var numbers = new[] { 10, 1, 10, 4, 17, 17, 122 }; 13 | 14 | //Distinct removes all duplicated values from the collection 15 | //returning a collaction of unique elements 16 | 17 | //duplicates of 10 and 17 will be removed 18 | var distinctNumbers = numbers.Distinct(); 19 | Printer.Print(distinctNumbers, nameof(distinctNumbers)); 20 | 21 | //below pets seem like duplicates, but they are not 22 | //those objects are compared by reference 23 | //in this case pets[0] == pets[1] will return false 24 | //that's why Distinct will not remove any of those items 25 | var pets = new[] 26 | { 27 | new Pet(1, "Hannibal", PetType.Fish, 1.1f), 28 | new Pet(1, "Hannibal", PetType.Fish, 1.1f) 29 | }; 30 | var distinctPets = pets.Distinct(); 31 | Printer.Print(distinctPets, nameof(distinctPets)); 32 | 33 | //we can use custom EqualityComparer 34 | //in this case Distinct will consider them duplicates 35 | //and remove one of them 36 | var petsDistinctById = pets.Distinct(new PetEqualityByIdComparer()); 37 | Printer.Print(petsDistinctById, nameof(petsDistinctById)); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /LinqTutorial/Examples/DotNet9Improvements.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data; 3 | using System.Linq; 4 | using Utilities; 5 | 6 | namespace LinqTutorial.MethodSyntax 7 | { 8 | static class DotNet9Improvements 9 | { 10 | public static void Run() 11 | { 12 | //CountBy 13 | 14 | //In older .NET versions, we woule need to use GroupBy with Select 15 | var petCountsByTypeOld = Data.Pets 16 | .GroupBy(pet => pet.PetType) 17 | .Select(group => new { Type = group.Key, Count = group.Count() }); 18 | 19 | Printer.Print(petCountsByTypeOld, nameof(petCountsByTypeOld)); 20 | 21 | //In .NET 9, we can use the CountBy method 22 | var petCountsByType = Data.Pets.CountBy(pet => pet.PetType); 23 | 24 | Printer.Print(petCountsByType, nameof(petCountsByType)); 25 | 26 | 27 | 28 | //AggregateBy 29 | 30 | //In older .NET versions, we woule need to use GroupBy with Select 31 | var totalWeightByTypeOld = Data.Pets 32 | .GroupBy(pet => pet.PetType) 33 | .Select(group => new { Type = group.Key, TotalWeight = group.Sum(pet => pet.Weight) }); 34 | 35 | Printer.Print(totalWeightByTypeOld, nameof(totalWeightByTypeOld)); 36 | 37 | //In .NET 9, we can use the AggregateBy method 38 | var totalWeightByType = Data.Pets.AggregateBy( 39 | pet => pet.PetType, 40 | 0.0f, 41 | (total, pet) => total + pet.Weight 42 | ); 43 | 44 | Printer.Print(totalWeightByType, nameof(totalWeightByType)); 45 | 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /LinqTutorial/Examples/ElementAt.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using Utilities; 3 | 4 | namespace LinqTutorial.MethodSyntax 5 | { 6 | static class ElementAt 7 | { 8 | //System.Linq.Enumerable.ElementAt 9 | //System.Linq.Enumerable.ElementAtOrDefault 10 | public static void Run() 11 | { 12 | //ElementAt 13 | //it accessed the item at given element 14 | var numbers = new[] { 10, 1, 4, 17, 122 }; 15 | var numberAtIndex3 = numbers.ElementAt(3); 16 | Printer.Print(numberAtIndex3, nameof(numberAtIndex3)); 17 | 18 | //for arrays we can use simple indexer instead of LINQ method: 19 | var numberAtIndex4 = numbers[4]; 20 | Printer.Print(numberAtIndex4, nameof(numberAtIndex4)); 21 | 22 | //we use ElementAt mostly when simple indexing is not supported. 23 | //the below line is not supported since Pets.Collection is an IEnumerable, 24 | //not an array 25 | //var petAtIndex3 = Pets.Collection[3]; 26 | 27 | var petAtIndex4 = Data.Pets.ElementAt(4); 28 | Printer.Print(petAtIndex4, nameof(petAtIndex4)); 29 | 30 | //if there is no element under the index, an exception is thrown: 31 | //var petAtIndex99 = Pets.Collection.ElementAt(99); 32 | 33 | //ElementAtOrDefault 34 | //we can use ElementAtOrDefault to avoid the exception 35 | //when there is no element under the index 36 | //the default value for the type will be used - in this case null 37 | var petAtIndex99OrDefault = Data.Pets.ElementAtOrDefault(99); 38 | Printer.Print(petAtIndex99OrDefault, nameof(petAtIndex99OrDefault)); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /LinqTutorial/Examples/FirstLast.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using Utilities; 3 | 4 | namespace LinqTutorial.MethodSyntax 5 | { 6 | static class FirstLast 7 | { 8 | //System.Linq.Enumerable.First 9 | //System.Linq.Enumerable.FirstOrDefault 10 | //System.Linq.Enumerable.Last 11 | //System.Linq.Enumerable.LastOrDefault 12 | public static void Run() 13 | { 14 | //First & Last 15 | var numbers = new[] { 10, 1, 4, 17, 122 }; 16 | 17 | var firstNumber = numbers.First(); 18 | Printer.Print(firstNumber, nameof(firstNumber)); 19 | 20 | var lastNumber = numbers.Last(); 21 | Printer.Print(lastNumber, nameof(lastNumber)); 22 | 23 | //we can also use First with a predicate 24 | var firstOddNumber = numbers.First(n => n % 2 != 0); 25 | Printer.Print(firstOddNumber, nameof(firstOddNumber)); 26 | 27 | var lastOddNumber = numbers.Last(n => n % 2 != 0); 28 | Printer.Print(lastOddNumber, nameof(lastOddNumber)); 29 | 30 | //an exception will be thrown if the collection is empty 31 | //or if there are no elements in the collection 32 | //that match the given predicate 33 | //var firstNumberLargerThan1000 = numbers.First(n => n > 1000); 34 | //var lastNumberLargerThan1000 = numbers.Last(n => n > 1000); 35 | 36 | //the First and Last methods are often used with OrderBy 37 | var heaviestPet = Data.Pets.OrderByDescending(pet => pet.Weight).First(); 38 | Printer.Print(heaviestPet, nameof(heaviestPet)); 39 | 40 | var lastPetAlphabetically = Data.Pets.OrderBy(pet => pet.Name).Last(); 41 | Printer.Print(lastPetAlphabetically, nameof(lastPetAlphabetically)); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /LinqTutorial/Examples/GroupJoin.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using Utilities; 3 | 4 | namespace LinqTutorial.MethodSyntax 5 | { 6 | static class GroupJoin 7 | { 8 | //System.Linq.Enumerable.GroupJoin 9 | public static void Run() 10 | { 11 | //GroupJoin method correlates the elements of two collections 12 | //based on some key, and groups the results 13 | 14 | //let's print something like this: 15 | //PetName1 - appointmentDate1, appointmentDate2 16 | //PetName2 - appointmentDate3 17 | //PetName3 - appointmentDate4, appointmentDate5 18 | var petsGroupedAppointments = Data.Pets 19 | .GroupJoin( 20 | Data.VeterinaryClinicAppointments, 21 | pet => pet.Id, 22 | appointmet => appointmet.PetId, 23 | (pet, appointments) => 24 | $"Pet: {pet.Name}, " + 25 | $"appointment dates: {string.Join(", ", appointments.Select(a => a.Date))}"); 26 | 27 | Printer.Print(petsGroupedAppointments, nameof(petsGroupedAppointments)); 28 | 29 | //now let's perform Left Join 30 | //Left Join returns all records from the left table, 31 | //and the matched records from the right table 32 | //in this case we want to print all Pet's data, 33 | //even if they don't have an appointment planned 34 | var leftJoin = Data.Pets.GroupJoin( 35 | Data.VeterinaryClinicAppointments, 36 | pet => pet.Id, 37 | appointmet => appointmet.PetId, 38 | (pet, appointments) => new { Pet = pet, Appointments = appointments }) 39 | //there can be zero or more appointments in the "petAppointments" collection 40 | .SelectMany(petAppointments => petAppointments.Appointments.DefaultIfEmpty(), 41 | //without DefaultOrEmpty there would be no appointments for a given pet 42 | //so it wouldn't be included in results from SelectMany method 43 | (petAppointment, appointment) => 44 | $"Pet name: {petAppointment.Pet.Name}, appointment date: {appointment?.Date}"); 45 | Printer.Print(leftJoin, nameof(leftJoin)); 46 | } 47 | } 48 | } 49 | 50 | -------------------------------------------------------------------------------- /LinqTutorial/Examples/MinMax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Utilities; 4 | 5 | namespace LinqTutorial 6 | { 7 | static class MinMax 8 | { 9 | //System.Linq.Enumerable.Min 10 | //System.Linq.Enumerable.Max 11 | public static void Run() 12 | { 13 | var numbers = new[] { 10, 1, 4, 17, 122 }; 14 | 15 | //Min returns the minimal number in the collection 16 | var minNumber = numbers.Min(); 17 | Console.WriteLine($"minNumber: {minNumber}"); 18 | 19 | //we can select some particular numeric value from a collection of objects 20 | var lightestPetWeight = Data.Pets.Min(pet => pet.Weight); 21 | Console.WriteLine($"lightestPetWeight: {lightestPetWeight}"); 22 | 23 | //Max works the same, but it returns the maximal number 24 | var maxNumber = numbers.Max(); 25 | Printer.Print(maxNumber, nameof(maxNumber)); 26 | 27 | var heaviestPetsWeight = Data.Pets.Max(pet => pet.Weight); 28 | Console.WriteLine($"heaviestPetsWeight: {heaviestPetsWeight}"); 29 | 30 | //if we don't pass the selector when finding 31 | //Min or Max of the collection that does not 32 | //implement the IComparable interface 33 | //an exception will be thrown 34 | //var minPet = Data.Pets.Min(); 35 | 36 | //Min and Max will throw an exception if the collection is empty 37 | //that's why the below code will not work 38 | //var emptyPetsCollection = new Pet[0]; 39 | //var lightestPetsWeight = emptyPetsCollection.Min(pet => pet.Weight); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /LinqTutorial/Examples/OfType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Utilities; 5 | 6 | namespace LinqTutorial 7 | { 8 | static class OfType 9 | { 10 | //System.Linq.Enumerable.OfType 11 | public static void Run() 12 | { 13 | //OfType returns all the objects of given type 14 | var objects = new object[] 15 | { 16 | null, 17 | 1, 18 | "all", 19 | 2, 20 | "ducks", 21 | new List(), 22 | "are", 23 | "awesome", 24 | true 25 | }; 26 | 27 | var strings = objects.OfType(); 28 | Printer.Print(strings, nameof(strings)); 29 | 30 | //it's often used when operating on multiple types with one interface 31 | var flyables = new List() 32 | { 33 | new Bird(), 34 | new Plane(), 35 | new Helicopter() 36 | }; 37 | 38 | var birds = flyables.OfType(); 39 | Printer.Print(birds, nameof(birds)); 40 | 41 | var fuelables = flyables.OfType(); 42 | Printer.Print(fuelables, nameof(fuelables)); 43 | } 44 | } 45 | 46 | interface IFlyable 47 | { 48 | public void Fly(); 49 | } 50 | 51 | interface IFuelable 52 | { 53 | public void Fuel(); 54 | } 55 | 56 | class Bird : IFlyable 57 | { 58 | public void Fly() 59 | { 60 | Console.WriteLine("Flying by flapping my wings"); 61 | } 62 | } 63 | 64 | class Plane : IFlyable, IFuelable 65 | { 66 | public void Fly() 67 | { 68 | Console.WriteLine("Flying by jet propulsion"); 69 | } 70 | 71 | public void Fuel() 72 | { 73 | Console.WriteLine("Fuelling my large gas tank"); 74 | } 75 | } 76 | 77 | class Helicopter : IFlyable, IFuelable 78 | { 79 | public void Fly() 80 | { 81 | Console.WriteLine("Flying by rotating my rotors"); 82 | } 83 | 84 | public void Fuel() 85 | { 86 | Console.WriteLine("Fuelling my gas tank"); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /LinqTutorial/Examples/PrependAppend.cs: -------------------------------------------------------------------------------- 1 | using LinqTutorial.DataTypes; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Utilities; 5 | 6 | namespace LinqTutorial.MethodSyntax 7 | { 8 | static class PrependAppend 9 | { 10 | //System.Linq.Enumerable.Prepend 11 | //System.Linq.Enumerable.Append 12 | public static void Run() 13 | { 14 | IEnumerable numbers = new[] { 10, 1, 4, 17, 122 }; 15 | //Prepend adds element at the beginning of the collection 16 | //please note that a new collection is created 17 | //the original collection is not modified 18 | var newNumbers = numbers.Prepend(99); 19 | Printer.Print(newNumbers, nameof(newNumbers)); 20 | Printer.Print(numbers, nameof(numbers)); 21 | 22 | //Append works the same, but it puts the element at the end of the collection 23 | var petsWithNewPet = Data.Pets.Append( 24 | new Pet(7, "Spark", PetType.Dog, 4f)); 25 | Printer.Print(petsWithNewPet, nameof(petsWithNewPet)); 26 | 27 | //Prepend and Append are often used together 28 | //let's say we had system where we can review restaurants 29 | //at first, we can select "Bad", "Medium" and "Good" grade 30 | //but after some time we want to also add "Terrible" and "Excellent" grades 31 | var originalGrades = new[] { "Bad", "Medium", "Good" }; 32 | var newGrades = originalGrades.Prepend("Terrible").Append("Excellent"); 33 | Printer.Print(newGrades, nameof(newGrades)); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /LinqTutorial/Examples/SingleElement.cs: -------------------------------------------------------------------------------- 1 | using LinqTutorial.DataTypes; 2 | using System.Linq; 3 | using Utilities; 4 | 5 | namespace LinqTutorial.MethodSyntax 6 | { 7 | static class SingleElement 8 | { 9 | //System.Linq.Enumerable.Single 10 | //System.Linq.Enumerable.SingleOrDefault 11 | public static void Run() 12 | { 13 | var numbers = new[] { 10, 1, 4, 17, 122 }; 14 | 15 | //Single 16 | //Returns the only element of a sequence that satisfies a specified condition, 17 | //and throws an exception if more than one such element exists. 18 | var number10 = numbers.Single(n => n == 10); 19 | Printer.Print(number10, nameof(number10)); 20 | 21 | //we can skip the predicate if we want to access the only element in the collection 22 | //this simply changes an one-element collection to a single value 23 | var numbers2 = new[] { 6 }; 24 | var singleNumber = numbers2.Single(); 25 | 26 | //but it will throw an exception if there are more than one elements in the collection 27 | //var singleNumber2 = numbers.Single(); 28 | 29 | //the below will thrown an exception 30 | //because there is no such element in this collection 31 | //var number99 = numbers.Single(n => n == 99); 32 | //Printer.Print(number99, nameof(number99)); 33 | 34 | //the below will thrown an exception 35 | //because there are more than one even numbers in this collection 36 | //var singleEvenNumber = numbers.Single(n => n % 2 == 0); 37 | //Printer.Print(singleEvenNumber, nameof(singleEvenNumber)); 38 | 39 | //SingleOrDefault 40 | //we can use SingleOrDefault to avoid the exception 41 | //when there is no such element in the collection 42 | //the default value for the type will be used - in this case 0 43 | var number99OrDefault = numbers.SingleOrDefault(n => n == 99); 44 | Printer.Print(number99OrDefault, nameof(number99OrDefault)); 45 | 46 | //the below will thrown an exception 47 | //because there are more than one even numbers in this collection 48 | //var singleOrDefaultEvenNumber = numbers.SingleOrDefault(n => n % 2 == 0); 49 | //Printer.Print(singleOrDefaultEvenNumber, nameof(singleOrDefaultEvenNumber)); 50 | 51 | var singleFish = Data.Pets.Single(pet => pet.PetType == PetType.Fish); 52 | Printer.Print(singleFish, nameof(singleFish)); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /LinqTutorial/Examples/Sum.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace LinqTutorial 5 | { 6 | static class Sum 7 | { 8 | //System.Linq.Enumerable.Sum 9 | public static void Run() 10 | { 11 | var numbers = new[] { 10, 1, 4, 17, 122 }; 12 | 13 | //Sum calculates the sum of the values 14 | var sumOfNumbers = numbers.Sum(); 15 | Console.WriteLine($"sumOfNumbers: {sumOfNumbers}"); 16 | 17 | var sumOfPetsWeight = Data.Pets.Sum(pet => pet.Weight); 18 | Console.WriteLine($"sumOfPetsWeight: {sumOfPetsWeight}"); 19 | 20 | //if the collection is empty, the sum will be zero 21 | //no exception will be thrown 22 | var emptyNumbers = new int[0]; 23 | var sum = emptyNumbers.Sum(); 24 | Console.WriteLine( 25 | $"sum of elements in an empty collection: {sum}"); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /LinqTutorial/Examples/Take.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using Utilities; 3 | 4 | namespace LinqTutorial 5 | { 6 | static class Take 7 | { 8 | //System.Linq.Enumerable.Take 9 | //System.Linq.Enumerable.TakeLast 10 | //System.Linq.Enumerable.TakeWhile 11 | public static void Run() 12 | { 13 | var numbers = new[] { 10, 1, 4, 17, 122 }; 14 | 15 | //Take 16 | //Take returns a specified number 17 | //of contiguous elements from the start of a sequence. 18 | var take3 = numbers.Take(3); 19 | Printer.Print(take3, nameof(take3)); 20 | 21 | //if we take more than collection size, 22 | //whole collection will be returned 23 | //no exception will be thrown 24 | var take20 = numbers.Take(20); 25 | Printer.Print(take20, nameof(take20)); 26 | 27 | //TakeLast 28 | var takeLast3 = numbers.TakeLast(3); 29 | Printer.Print(takeLast3, nameof(takeLast3)); 30 | 31 | //let's say we want to pick the 2 largest numbers 32 | var twoLargestNumbers = numbers.OrderBy(n => n).TakeLast(2); 33 | Printer.Print(twoLargestNumbers, nameof(twoLargestNumbers)); 34 | 35 | //let's say we want to pick the second largest number 36 | var secondLargestNumber = numbers.OrderBy(n => n).TakeLast(2).First(); 37 | Printer.Print(secondLargestNumber, nameof(secondLargestNumber)); 38 | 39 | //let's take 60% of the pets 40 | var sixtyPercentOfPets = Data.Pets.Take((int)(Data.Pets.Count() * 0.6)); 41 | Printer.Print(sixtyPercentOfPets, nameof(sixtyPercentOfPets)); 42 | 43 | //TakeWhile 44 | var numbers2 = new[] { 1, 4, 10, 154, 999 }; 45 | var takeWhileSmallerThan20 = numbers2.TakeWhile(n => n < 20); 46 | Printer.Print(takeWhileSmallerThan20, nameof(takeWhileSmallerThan20)); 47 | 48 | //let's take pets until we "hit" a pet heavier than 30 kilos 49 | var takeWhileLighterThan30 = Data.Pets.TakeWhile(pet => pet.Weight < 30); 50 | Printer.Print(takeWhileLighterThan30, nameof(takeWhileLighterThan30)); 51 | 52 | //let's do the same but until we "hit" a pet LIGHTER than 30 kilos 53 | //the collection will be empty because the first pet is lighter than 30 kilos, 54 | //so while we process the first element the predicate will be false, 55 | //so we will not Take even one element 56 | var takeWhileHeavierThan30 = Data.Pets.TakeWhile(pet => pet.Weight > 30); 57 | Printer.Print(takeWhileHeavierThan30, nameof(takeWhileHeavierThan30)); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /LinqTutorial/LinqTutorial.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net9.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /LinqTutorial/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using LinqTutorial.MethodSyntax; 3 | 4 | namespace LinqTutorial 5 | { 6 | class Program 7 | { 8 | static void Main(string[] args) 9 | { 10 | //METHOD SYNTAX 11 | 12 | //Any.Run(); 13 | //All.Run(); 14 | //Count.Run(); 15 | //Contains.Run(); 16 | //OrderBy.Run(); 17 | //MinMax.Run(); 18 | //Average.Run(); 19 | //Sum.Run(); 20 | //ElementAt.Run(); 21 | //FirstLast.Run(); 22 | //SingleElement.Run(); 23 | //Where.Run(); 24 | //Take.Run(); 25 | //Skip.Run(); 26 | //OfType.Run(); 27 | //Distinct.Run(); 28 | //PrependAppend.Run(); 29 | //ConcatUnion.Run(); 30 | //TypeSwitching.Run(); 31 | //Select.Run(); 32 | //SelectMany.Run(); 33 | //GeneratingNewCollection.Run(); 34 | //GroupBy.Run(); 35 | //IntersectExcept.Run(); 36 | //Joins.Run(); 37 | //Aggregate.Run(); 38 | //Zip.Run(); 39 | 40 | //QUERY SYNTAX 41 | 42 | //OrderBy.QuerySyntax.Run(); 43 | //Where.QuerySyntax.Run(); 44 | //Select.QuerySyntax.Run(); 45 | //SelectMany.QuerySyntax.Run(); 46 | //GroupBy.QuerySyntax.Run(); 47 | //Joins.QuerySyntax.Run(); 48 | 49 | //OTHERS 50 | //DotNet6Improvements.Run(); 51 | //DotNet9Improvements.Run(); 52 | 53 | Console.ReadKey(); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LinqTutorial 2 | 3 | Hello! 4 | 5 | My name is Krystyna and welcome to my GitHub. 6 | 7 | This repository is part of my "LINQ Tutorial: Master the Key C# Library" course, which you can find under this link: https://www.udemy.com/course/linq-tutorial-master-the-key-csharp-library/?referralCode=384B340D233F12F6A498 8 | 9 | ## FAQ: 10 | 11 | ### Q1: How do I download the files? 12 | A: If you're not familiar with GitHub and just want to download the entire solution, click the green button saying "Code", and then select the "Download ZIP". 13 | 14 | ### Q2: What are the projects in this solution? 15 | A: The solution consists of 4 main projects: 16 | #### LinqTutorial 17 | Contains the code shown in the course's videos. 18 | #### Exercises 19 | Contains coding exercises that you can solve to practice LINQ. 20 | #### ExercisesSolutions 21 | Contains solved versions of the coding exercises. You can take a look at them to check how some exercise can be solved. 22 | #### ExercisesTests 23 | Contains unit tests which validate if your solutions of exercises are correct (the solutions from the Exercises project are validated). 24 | 25 | ### Q3: How to approach solving coding exercises? 26 | Let's say you want to practice using the Any method from LINQ. Go to Exercises project and open Any.cs file. 27 | 28 | If you want to solve coding exercise 1, find the method with a comment describing what this method should do. 29 | 30 | Before you solve the exercise, you can run unit tests that validate if it is correct. To do it, build the solution first. Then you can click on Test in the top menu of Visual Studio, and then Run All Test. In the Test Explorer window that will be open, you can unfold the list of tests that has been run. The tests for the Any should fail, because you haven't yet implement it.The failed tests are marked in red. 31 | 32 | You can also run or debug a single test, which is described in the next point. 33 | 34 | Now, you can implement the method, so it does what the description of the exercise says. If your solution is correct, and you run the tests again, you will see that tests for the first exercise for the Any method should pass, and they will be marked in green. 35 | 36 | ### Q3: How to debug the code of the coding exercise? 37 | Place a breakpoint in the place that you are interested in. 38 | 39 | Now, find the unit test that you want to run. To run it in the Debug mode, you can either right-click on it the the Test Explorer and select debug, or you can left click on the test marker just at the test body and select debug. Both places are shown in the image: 40 | 41 | ![image](https://user-images.githubusercontent.com/89634343/218571108-b4cf876b-45a9-4c20-be73-1efd44dee9ad.png) 42 | 43 | -------------------------------------------------------------------------------- /Utilities/Printer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Collections.Generic; 4 | 5 | namespace Utilities 6 | { 7 | public static class Printer 8 | { 9 | public static void Print(T item, string itemName) 10 | { 11 | Console.WriteLine($"{itemName}: {item}"); 12 | } 13 | 14 | public static void Print(IEnumerable collection, string collectionName) 15 | { 16 | Print(collection, collectionName, "collection"); 17 | } 18 | 19 | public static void Print(IOrderedEnumerable collection, string collectionName) 20 | { 21 | Print(collection as IEnumerable, collectionName, "collection"); 22 | } 23 | 24 | public static void Print(List collection, string collectionName) 25 | { 26 | Print(collection as IEnumerable, collectionName, "collection"); 27 | } 28 | 29 | public static void Print(HashSet hashSet, string hashSetName) 30 | { 31 | Print(hashSet, hashSetName, "HashSet"); 32 | } 33 | 34 | private static void Print(IEnumerable collection, string collectionName, string collectionType) 35 | { 36 | Console.WriteLine($"{collectionName}:"); 37 | if (collection.Any()) 38 | { 39 | Console.WriteLine(string.Join("\n", collection.Select(elem => elem.ToString()))); 40 | } 41 | else 42 | { 43 | Console.WriteLine($"The {collectionType} is empty!"); 44 | } 45 | } 46 | 47 | public static void Print(Dictionary dictionary, string dictionaryName) 48 | { 49 | Console.WriteLine($"{dictionaryName}:"); 50 | if (dictionary.Any()) 51 | { 52 | Console.WriteLine(string.Join("\n", dictionary.Select( 53 | elem => $"Key: {elem.Key}, Value: {elem.Value}"))); 54 | } 55 | else 56 | { 57 | Console.WriteLine("The dictionary is empty!"); 58 | } 59 | } 60 | 61 | public static void Print(ILookup lookup, string lookupName) 62 | { 63 | Console.WriteLine($"{lookupName}:"); 64 | if (lookup.Any()) 65 | { 66 | Console.WriteLine(string.Join("\n", lookup.Select( 67 | elem => $"Key: {elem.Key}, Values (count: {lookup[elem.Key].Count()}): {string.Join(", ", lookup[elem.Key])}"))); 68 | } 69 | else 70 | { 71 | Console.WriteLine("The lookup is empty!"); 72 | } 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Utilities/Utilities.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Library 5 | net9.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | --------------------------------------------------------------------------------