├── .gitignore ├── LinqCourseEmbeddedCode ├── AllTogether1.cs ├── Background1.cs ├── LinqConcepts1.cs ├── LinqCourseEmbeddedCode.csproj ├── LinqCourseEmbeddedCode.sln ├── Methods1.cs ├── Methods2.cs ├── Methods3.cs ├── Methods4.cs └── Methods5.cs ├── README.md ├── cover.png ├── cover.xcf ├── embed_examples.pl ├── markdowns ├── 01_AboutThisCourse │ ├── 01_welcome.md │ ├── 01_welcome.template.md │ ├── 02_introduction.md │ └── 02_introduction.template.md ├── 02_Background │ ├── 01_background_intro.md │ ├── 01_background_intro.template.md │ ├── 02_lambda_expressions.md │ ├── 02_lambda_expressions.template.md │ ├── 03_ienumerable.md │ ├── 03_ienumerable.template.md │ ├── 04_to_list_to_array.md │ └── 04_to_list_to_array.template.md ├── 03_LinqConcepts │ ├── 01_concepts_intro.md │ ├── 01_concepts_intro.template.md │ ├── 02_query_syntax.md │ ├── 02_query_syntax.template.md │ ├── 03_method_syntax.md │ └── 03_method_syntax.template.md ├── 04_MethodsExtractAValue │ ├── 01_first_last_single.md │ ├── 01_first_last_single.template.md │ ├── 02_conditions.md │ ├── 02_conditions.template.md │ ├── 03_or_default.md │ ├── 03_or_default.template.md │ ├── 04_single_value_exercise.md │ └── 04_single_value_exercise.template.md ├── 05_MethodsExtractValues │ ├── 01_skip_take.md │ ├── 01_skip_take.template.md │ ├── 02_skip_while_take_while.md │ ├── 02_skip_while_take_while.template.md │ ├── 03_distinct_intersection_where.md │ └── 03_distinct_intersection_where.template.md ├── 06_MethodsOrderElements │ ├── 01_reverse_orderby.md │ ├── 01_reverse_orderby.template.md │ ├── 02_thenby.md │ └── 02_thenby.template.md ├── 07_MethodsCalculateSingleValue │ ├── 01_count.md │ ├── 01_count.template.md │ ├── 02_sum.md │ ├── 02_sum.template.md │ ├── 03_min_max.md │ ├── 03_min_max.template.md │ ├── 04_any_all.md │ ├── 04_any_all.template.md │ ├── 05_sequenceequal.md │ ├── 05_sequenceequal.template.md │ ├── 06_aggregate.md │ └── 06_aggregate.template.md ├── 08_MethodsCalculateSequence │ ├── 01_cast.md │ ├── 01_cast.template.md │ ├── 02_select.md │ ├── 02_select.template.md │ ├── 03_selectmany.md │ └── 03_selectmany.template.md ├── 09_AllTogether │ ├── 01_together.md │ ├── 01_together.template.md │ ├── 02_together.md │ └── 02_together.template.md └── 10_FinalWords │ ├── 01_review.md │ ├── 01_review.template.md │ ├── 02_what_next.md │ └── 02_what_next.template.md ├── post-commit ├── pre-commit ├── projects ├── LinqExercises.sln ├── LinqExercises │ ├── AllTogether1 │ │ ├── AllTogether1.cs │ │ ├── AllTogether2.cs │ │ └── UnitTest.cs │ ├── Background1 │ │ ├── LambdaExpressions1.cs │ │ └── UnitTest.cs │ ├── CalculatedSequence1 │ │ ├── Select1.cs │ │ └── UnitTest.cs │ ├── ChangeOrder1 │ │ ├── OrderBy1.cs │ │ ├── ThenBy1.cs │ │ └── UnitTest.cs │ ├── LinqExercises.csproj │ ├── MethodSyntax1 │ │ ├── MethodSyntax1.cs │ │ └── UnitTest.cs │ ├── MultipleValue1 │ │ ├── DistinctIntersectWhere1.cs │ │ ├── SkipTake1.cs │ │ ├── SkipTakeWhile1.cs │ │ └── UnitTest.cs │ ├── QuerySyntax1 │ │ ├── QuerySyntax1.cs │ │ └── UnitTest.cs │ ├── SingleCalculatedValue1 │ │ ├── Aggregate1.cs │ │ ├── Count1.cs │ │ ├── MinMax1.cs │ │ └── UnitTest.cs │ ├── SingleValue1 │ │ ├── SingleValue1.cs │ │ └── UnitTest.cs │ ├── Utils │ │ └── Utils.cs │ └── report.html └── LinqExercises_sanitized │ ├── AllTogether1 │ ├── AllTogether1.cs │ ├── AllTogether1.cs.orig │ ├── AllTogether2.cs │ ├── AllTogether2.cs.orig │ ├── UnitTest.cs │ └── UnitTest.cs.orig │ ├── Background1 │ ├── LambdaExpressions1.cs │ ├── LambdaExpressions1.cs.orig │ ├── UnitTest.cs │ └── UnitTest.cs.orig │ ├── CalculatedSequence1 │ ├── Select1.cs │ ├── Select1.cs.orig │ ├── UnitTest.cs │ └── UnitTest.cs.orig │ ├── ChangeOrder1 │ ├── OrderBy1.cs │ ├── OrderBy1.cs.orig │ ├── ThenBy1.cs │ ├── ThenBy1.cs.orig │ ├── UnitTest.cs │ └── UnitTest.cs.orig │ ├── LinqExercises.csproj │ ├── LinqExercises.csproj.orig │ ├── MethodSyntax1 │ ├── MethodSyntax1.cs │ ├── MethodSyntax1.cs.orig │ ├── UnitTest.cs │ └── UnitTest.cs.orig │ ├── MultipleValue1 │ ├── DistinctIntersectWhere1.cs │ ├── DistinctIntersectWhere1.cs.orig │ ├── SkipTake1.cs │ ├── SkipTake1.cs.orig │ ├── SkipTakeWhile1.cs │ ├── SkipTakeWhile1.cs.orig │ ├── UnitTest.cs │ └── UnitTest.cs.orig │ ├── QuerySyntax1 │ ├── QuerySyntax1.cs │ ├── QuerySyntax1.cs.orig │ ├── UnitTest.cs │ └── UnitTest.cs.orig │ ├── SingleCalculatedValue1 │ ├── Aggregate1.cs │ ├── Aggregate1.cs.orig │ ├── Count1.cs │ ├── Count1.cs.orig │ ├── MinMax1.cs │ ├── MinMax1.cs.orig │ ├── UnitTest.cs │ └── UnitTest.cs.orig │ ├── SingleValue1 │ ├── SingleValue1.cs │ ├── SingleValue1.cs.orig │ ├── UnitTest.cs │ └── UnitTest.cs.orig │ ├── Utils │ ├── Utils.cs │ └── Utils.cs.orig │ ├── report.html │ └── report.html.orig ├── remove_md_files.pl ├── sanitize_projects.pl └── techio.yml /.gitignore: -------------------------------------------------------------------------------- 1 | projects/**/bin 2 | projects/**/obj 3 | projects/.vs 4 | LinqCourseEmbeddedCode/**/bin 5 | LinqCourseEmbeddedCode/**/obj 6 | LinqCourseEmbeddedCode/.vs 7 | **/.*.swp 8 | -------------------------------------------------------------------------------- /LinqCourseEmbeddedCode/AllTogether1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | namespace LinqCourseEmbeddedCode 7 | { 8 | [TestClass] 9 | public class AllTogether1 10 | { 11 | [TestMethod] 12 | public void TestMethod1() 13 | { 14 | //// START EMBED: All Together //// 15 | IEnumerable values = new List { "fe", "fi", "fo", "fum" }; 16 | // Will return 12 17 | int result = values 18 | .Select(word => $"{word}-{word}") // { "fe-fe", "fi-fi", ... } 19 | .Skip(2) 20 | .Select(phrase => phrase.Length) 21 | .Sum(); 22 | //// END EMBED //// 23 | Assert.AreEqual(result, 12); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /LinqCourseEmbeddedCode/Background1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | 7 | namespace LinqCourseEmbeddedCode 8 | { 9 | [TestClass] 10 | public class Background1 11 | { 12 | [TestMethod] 13 | public void TestMethod1() 14 | { 15 | //// START EMBED: Lambda 1 //// 16 | Func multiplyByFive = num => num * 5; 17 | // Returns 35 18 | int result = multiplyByFive(7); 19 | //// END EMBED //// 20 | Assert.AreEqual(35, result); 21 | } 22 | 23 | [TestMethod] 24 | public void TestMethod2() 25 | { 26 | //// START EMBED: Lambda 2 //// 27 | Func multiplyTwoNumbers = (a, b) => a * b; 28 | // Returns 35 29 | int result = multiplyTwoNumbers(7, 5); 30 | //// END EMBED //// 31 | Assert.AreEqual(35, result); 32 | } 33 | 34 | [TestMethod] 35 | public void TestMethod3() 36 | { 37 | //// START EMBED: Lambda 3 //// 38 | Func multiplyByFive = num => 39 | { 40 | int product = num * 5; 41 | return product; 42 | }; 43 | // Returns 35 44 | int result = multiplyByFive(7); 45 | //// END EMBED //// 46 | Assert.AreEqual(35, result); 47 | } 48 | 49 | [TestMethod] 50 | public void TestMethod4() 51 | { 52 | //// START EMBED: IEnumerable examples //// 53 | IEnumerable list = new List { 1, 2, 3 }; 54 | IEnumerable array = new[] { 1, 2, 3 }; 55 | IEnumerable set = new SortedSet { 1, 2, 3 }; 56 | //// END EMBED //// 57 | Assert.IsTrue(list.SequenceEqual(array)); 58 | Assert.IsTrue(list.SequenceEqual(set)); 59 | } 60 | 61 | [TestMethod] 62 | public void TestMethod5() 63 | { 64 | //// START EMBED: ToList() and ToArray() //// 65 | List list = new[] {1, 2, 3}.ToList(); 66 | int[] array = new List {1, 2, 3}.ToArray(); 67 | List list2 = new SortedSet {1, 2, 3}.ToList(); 68 | //// END EMBED //// 69 | Assert.IsTrue(list.SequenceEqual(array)); 70 | Assert.IsTrue(list.SequenceEqual(list2)); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /LinqCourseEmbeddedCode/LinqConcepts1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using System.Collections.Generic; 4 | //// START EMBED: using System.Linq //// 5 | using System.Linq; 6 | //// END EMBED //// 7 | 8 | namespace LinqCourseEmbeddedCode 9 | { 10 | [TestClass] 11 | public class LinqConcepts1 12 | { 13 | [TestMethod] 14 | public void TestMethod1() 15 | { 16 | //// START EMBED: LINQ query syntax //// 17 | List animalNames = new List 18 | {"fawn", "gibbon", "heron", "ibex", "jackalope"}; 19 | 20 | // Result: {"heron", "gibbon", "jackalope"} 21 | IEnumerable longAnimalNames = 22 | from name in animalNames 23 | where name.Length >= 5 24 | orderby name.Length 25 | select name; 26 | //// END EMBED //// 27 | 28 | Assert.IsTrue((new List{"heron", "gibbon", "jackalope"}).SequenceEqual(longAnimalNames)); 29 | } 30 | 31 | [TestMethod] 32 | public void TestMethod2() 33 | { 34 | //// START EMBED: LINQ method syntax //// 35 | List animalNames = new List 36 | {"fawn", "gibbon", "heron", "ibex", "jackalope"}; 37 | 38 | IEnumerable longAnimalNames = 39 | animalNames 40 | .Where(name => name.Length >= 5) 41 | .OrderBy(name => name.Length); 42 | //// END EMBED //// 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /LinqCourseEmbeddedCode/LinqCourseEmbeddedCode.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp1.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /LinqCourseEmbeddedCode/LinqCourseEmbeddedCode.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26403.3 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LinqCourseEmbeddedCode", "LinqCourseEmbeddedCode.csproj", "{9B1CB7BA-E312-4258-8353-E669D0AA8AEA}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {9B1CB7BA-E312-4258-8353-E669D0AA8AEA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {9B1CB7BA-E312-4258-8353-E669D0AA8AEA}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {9B1CB7BA-E312-4258-8353-E669D0AA8AEA}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {9B1CB7BA-E312-4258-8353-E669D0AA8AEA}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /LinqCourseEmbeddedCode/Methods2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Diagnostics; 6 | 7 | namespace LinqCourseEmbeddedCode 8 | { 9 | [TestClass] 10 | public class Methods2 11 | { 12 | [TestMethod] 13 | public void TestMethod1() 14 | { 15 | //// START EMBED: Take() //// 16 | List bools = new List { true, false, true, true, false }; 17 | // Will contain { true, false, true } 18 | IEnumerable result = bools.Take(3); 19 | //// END EMBED //// 20 | Assert.IsTrue(result.SequenceEqual(new List { true, false, true })); 21 | } 22 | 23 | [TestMethod] 24 | public void TestMethod2() 25 | { 26 | //// START EMBED: Skip() //// 27 | List bools = new List { true, false, true, true, false }; 28 | // Will contain { true, true, false } 29 | IEnumerable result = bools.Skip(2); 30 | //// END EMBED //// 31 | Assert.IsTrue(result.SequenceEqual(new List { true, true, false })); 32 | } 33 | 34 | [TestMethod] 35 | public void TestMethod3() 36 | { 37 | //// START EMBED: TakeWhile() //// 38 | List ints = new List { 1, 2, 4, 8, 4, 2, 1 }; 39 | // Will contain { 1, 2, 4 } 40 | IEnumerable result = ints.TakeWhile(theInt => theInt < 5); 41 | //// END EMBED //// 42 | Assert.IsTrue(result.SequenceEqual(new List { 1, 2, 4 })); 43 | } 44 | 45 | [TestMethod] 46 | public void TestMethod4() 47 | { 48 | //// START EMBED: SkipWhile() //// 49 | List ints = new List { 1, 2, 4, 8, 4, 2, 1 }; 50 | // Will contain { 4, 8, 4, 2, 1 } 51 | IEnumerable result = ints.SkipWhile(theInt => theInt != 4); 52 | //// END EMBED //// 53 | Assert.IsTrue(result.SequenceEqual(new List { 4, 8, 4, 2, 1 })); 54 | } 55 | 56 | [TestMethod] 57 | public void TestMethod5() 58 | { 59 | //// START EMBED: Distinct() //// 60 | List ints = new List { 1, 2, 4, 8, 4, 2, 1 }; 61 | // Will contain { 1, 2, 4, 8 } 62 | IEnumerable result = ints.Distinct(); 63 | //// END EMBED //// 64 | Assert.IsTrue(result.SequenceEqual(new List { 1, 2, 4, 8 })); 65 | } 66 | 67 | [TestMethod] 68 | public void TestMethod6() 69 | { 70 | //// START EMBED: Intersect() //// 71 | List ints = new List { 1, 2, 4, 8, 4, 2, 1 }; 72 | List filter = new List { 1, 1, 2, 3, 5, 8 }; 73 | // Will contain { 1, 2, 8 } 74 | IEnumerable result = ints.Intersect(filter); 75 | //// END EMBED //// 76 | Debug.WriteLine(string.Join(" ", result)); 77 | Assert.IsTrue(result.SequenceEqual(new List { 1, 2, 8 })); 78 | } 79 | 80 | [TestMethod] 81 | public void TestMethod7() 82 | { 83 | //// START EMBED: Where() //// 84 | List ints = new List { 1, 2, 4, 8, 4, 2, 1 }; 85 | // Will contain { 2, 4, 4, 2 } 86 | IEnumerable result = ints.Where(theInt => theInt == 2 || theInt == 4); 87 | //// END EMBED //// 88 | Debug.WriteLine(string.Join(" ", result)); 89 | Assert.IsTrue(result.SequenceEqual(new List { 2, 4, 4, 2 })); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danBhentschel/techio-practical-linq/807de92212903a355954e81489e19fd76820ca2a/cover.png -------------------------------------------------------------------------------- /cover.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danBhentschel/techio-practical-linq/807de92212903a355954e81489e19fd76820ca2a/cover.xcf -------------------------------------------------------------------------------- /markdowns/01_AboutThisCourse/01_welcome.md: -------------------------------------------------------------------------------- 1 | [//]: # (GENERATED FILE -- DO NOT EDIT) 2 | # Using C# LINQ - A Practical Overview 3 | Welcome to **Using C# LINQ**. This course is designed as an introduction to using LINQ in the C# language. 4 | 5 | ## Who Will the Course Benefit? 6 | - C# developers who want to learn more about LINQ 7 | - Developers who may not know much C# but want to get a preview of some of the more powerful language features 8 | 9 | ## Course Content 10 | The lesson plan starts out with some brief and simple background information, followed by an explanation of what LINQ is and where you would use it. It then introduces students to 27 different LINQ methods. Similar methods are grouped together to aid comprehension and retention. The course ends with some exercises geared towards using LINQ methods in conjunction. 11 | 12 | ## Supplementary Courses 13 | There are two supplementary LINQ courses designed to be taken along with this course: 14 | - [C# LINQ Background Topics](https://tech.io/playgrounds/345) 15 | - **C# LINQ Advanced Topics** (LINK TBD) 16 | 17 | Neither supplementary course is required for the **Using C# LINQ** course. You may want to take the **Background** course before (or after) this one, but it is only recommended for advanced programmers. Beginners may be confused by some of the content. 18 | 19 | The **Advanced** course provides some hints and precautions for how to get the most out of LINQ while avoiding some of its pitfalls. It should be taken after the **Using** course, but beginning programmers might want to skip this course as well. The **Advanced** course is not required to be able to use LINQ in most situations. 20 | 21 | ## Previous Knowledge 22 | The lessons provided here are geared towards beginner to intermediate programmers. Students should have a basic understanding of the fundamentals of C#. Required skills include crafting of classes, fields, and methods. A good understanding of C# data types is also strongly recommended. 23 | 24 | ## Difficulty Level 25 | Beginner / Intermediate 26 | 27 | ## Estimated Time 28 | About 2 hours 29 | 30 | ## GitHub Repository 31 | This course is stored in a GitHub repository. You can not only see how the course was created, but there are solutions to all the exercises in there as well. Also, if you have any recommendations for improvement, feel free to fork the repository and create a pull request! 32 | 33 | [techio-practical-linq](https://github.com/danBhentschel/techio-practical-linq) 34 | 35 | ## Current Course Version 36 | 1.2 37 | 38 | ## Course Revision History 39 | 2017-07-28 - Add link to GitHub
40 | 2017-07-27 - Add links to the Background Topics course
41 | 2017-07-10 - Published 42 | -------------------------------------------------------------------------------- /markdowns/01_AboutThisCourse/01_welcome.template.md: -------------------------------------------------------------------------------- 1 | # Using C# LINQ - A Practical Overview 2 | Welcome to **Using C# LINQ**. This course is designed as an introduction to using LINQ in the C# language. 3 | 4 | ## Who Will the Course Benefit? 5 | - C# developers who want to learn more about LINQ 6 | - Developers who may not know much C# but want to get a preview of some of the more powerful language features 7 | 8 | ## Course Content 9 | The lesson plan starts out with some brief and simple background information, followed by an explanation of what LINQ is and where you would use it. It then introduces students to 27 different LINQ methods. Similar methods are grouped together to aid comprehension and retention. The course ends with some exercises geared towards using LINQ methods in conjunction. 10 | 11 | ## Supplementary Courses 12 | There are two supplementary LINQ courses designed to be taken along with this course: 13 | - [C# LINQ Background Topics](https://tech.io/playgrounds/345) 14 | - **C# LINQ Advanced Topics** (LINK TBD) 15 | 16 | Neither supplementary course is required for the **Using C# LINQ** course. You may want to take the **Background** course before (or after) this one, but it is only recommended for advanced programmers. Beginners may be confused by some of the content. 17 | 18 | The **Advanced** course provides some hints and precautions for how to get the most out of LINQ while avoiding some of its pitfalls. It should be taken after the **Using** course, but beginning programmers might want to skip this course as well. The **Advanced** course is not required to be able to use LINQ in most situations. 19 | 20 | ## Previous Knowledge 21 | The lessons provided here are geared towards beginner to intermediate programmers. Students should have a basic understanding of the fundamentals of C#. Required skills include crafting of classes, fields, and methods. A good understanding of C# data types is also strongly recommended. 22 | 23 | ## Difficulty Level 24 | Beginner / Intermediate 25 | 26 | ## Estimated Time 27 | About 2 hours 28 | 29 | ## GitHub Repository 30 | This course is stored in a GitHub repository. You can not only see how the course was created, but there are solutions to all the exercises in there as well. Also, if you have any recommendations for improvement, feel free to fork the repository and create a pull request! 31 | 32 | [techio-practical-linq](https://github.com/danBhentschel/techio-practical-linq) 33 | 34 | ## Current Course Version 35 | 1.2 36 | 37 | ## Course Revision History 38 | 2017-07-28 - Add link to GitHub
39 | 2017-07-27 - Add links to the Background Topics course
40 | 2017-07-10 - Published 41 | -------------------------------------------------------------------------------- /markdowns/01_AboutThisCourse/02_introduction.md: -------------------------------------------------------------------------------- 1 | [//]: # (GENERATED FILE -- DO NOT EDIT) 2 | # Introduction 3 | 4 | The C# programming language is quite popular with developers, in large part because of its many powerful and intuitive language features. One of these impressive (and fun, in a nerdy way) features is LINQ. 5 | 6 | ## What is LINQ? 7 | [LINQ](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/getting-started-with-linq) is a libary used to execute queries directly in C# syntax against many types of data. It is implemented as a set of **extension methods** on the `IEnumerable` interface. 8 | 9 | > **NOTE:** More informaiton on extension methods and `IEnumerable` can be found in the [LINQ Background Topics](https://tech.io/playgrounds/345) course. 10 | 11 | ## LINQ != SQL 12 | The acronym LINQ stands for Language Integrated Query. LINQ syntax is roughly derived from SQL. New C# developers often misinterpret this to mean that LINQ is a database access API. Although it is true that LINQ was conceived as a way to access data in a database from code, that is not the extent of its utility. 13 | 14 | 15 | ## The LINQ paradigm 16 | The LINQ paradigm describes a method for programmatically accessing and manipulating any data, independent of the source. There are many implementations of LINQ, each written to access a different kind of data source. Some of the common ones include: LINQ to SQL, LINQ to XML, and LINQ to Objects. 17 | 18 | ## LINQ to Objects 19 | Although this course works with LINQ to Objects, many of the concepts learned here can be applied to other LINQ implementations. LINQ to Objects provides access to data stored in C# collections such as lists and arrays. 20 | -------------------------------------------------------------------------------- /markdowns/01_AboutThisCourse/02_introduction.template.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | The C# programming language is quite popular with developers, in large part because of its many powerful and intuitive language features. One of these impressive (and fun, in a nerdy way) features is LINQ. 4 | 5 | ## What is LINQ? 6 | [LINQ](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/getting-started-with-linq) is a libary used to execute queries directly in C# syntax against many types of data. It is implemented as a set of **extension methods** on the `IEnumerable` interface. 7 | 8 | > **NOTE:** More informaiton on extension methods and `IEnumerable` can be found in the [LINQ Background Topics](https://tech.io/playgrounds/345) course. 9 | 10 | ## LINQ != SQL 11 | The acronym LINQ stands for Language Integrated Query. LINQ syntax is roughly derived from SQL. New C# developers often misinterpret this to mean that LINQ is a database access API. Although it is true that LINQ was conceived as a way to access data in a database from code, that is not the extent of its utility. 12 | 13 | 14 | ## The LINQ paradigm 15 | The LINQ paradigm describes a method for programmatically accessing and manipulating any data, independent of the source. There are many implementations of LINQ, each written to access a different kind of data source. Some of the common ones include: LINQ to SQL, LINQ to XML, and LINQ to Objects. 16 | 17 | ## LINQ to Objects 18 | Although this course works with LINQ to Objects, many of the concepts learned here can be applied to other LINQ implementations. LINQ to Objects provides access to data stored in C# collections such as lists and arrays. 19 | -------------------------------------------------------------------------------- /markdowns/02_Background/01_background_intro.md: -------------------------------------------------------------------------------- 1 | [//]: # (GENERATED FILE -- DO NOT EDIT) 2 | # Background Topics - Introduction 3 | 4 | Yes, there is an entire course on [LINQ Background Topics](https://tech.io/playgrounds/345). Why do we need a section here on background topics? 5 | 6 | The **Background** course is advanced material and takes a deep-dive approach to subjects such as: delegates, generators, and extension methods. On the other hand, this background chapter is intended for beginners. It is for those students who have little or no knowledge of lambda expressions, generics, etc. 7 | 8 | A very basic understanding of these concepts is pretty much required to effectively use LINQ. If you already are familiar with this material or you have already taken the **Background Topics** course, you can probably skim through or even skip this chapter. 9 | -------------------------------------------------------------------------------- /markdowns/02_Background/01_background_intro.template.md: -------------------------------------------------------------------------------- 1 | # Background Topics - Introduction 2 | 3 | Yes, there is an entire course on [LINQ Background Topics](https://tech.io/playgrounds/345). Why do we need a section here on background topics? 4 | 5 | The **Background** course is advanced material and takes a deep-dive approach to subjects such as: delegates, generators, and extension methods. On the other hand, this background chapter is intended for beginners. It is for those students who have little or no knowledge of lambda expressions, generics, etc. 6 | 7 | A very basic understanding of these concepts is pretty much required to effectively use LINQ. If you already are familiar with this material or you have already taken the **Background Topics** course, you can probably skim through or even skip this chapter. 8 | -------------------------------------------------------------------------------- /markdowns/02_Background/02_lambda_expressions.md: -------------------------------------------------------------------------------- 1 | [//]: # (GENERATED FILE -- DO NOT EDIT) 2 | # Background Topics - Lambda expressions 3 | 4 | A lambda expression is a convenient way of defining an anonymous (unnamed) function that can be passed around as a variable or as a parameter to a method call. Many LINQ methods take a function (called a **delegate**) as a parameter. Here is an example of what a lambda expression looks like: 5 | 6 | ```csharp 7 | Func multiplyByFive = num => num * 5; 8 | // Returns 35 9 | int result = multiplyByFive(7); 10 | ``` 11 | 12 | The expression `num => num * 5` is a lambda expression. The `=>` operator is called the "lambda operator". In this example, `num` is an input parameter to the anonymous function, and the return value of this function is `num * 5`. So when `multiplyByFive` is called with a parameter of `7`, the result is `7 * 5`, or `35`. 13 | 14 | ## Parameter(s) 15 | Notice that the `num` parameter doesn't explicitly specify a data type. The compiler always infers the data type of lambda expression parameters from context. In this case, the context is that the lambda expression is stored in a variable of type `Func`. This means that it takes an `int` parameter and returns an `int` result. 16 | 17 | You can also create lambda expressions with more than one parameter, as shown here: 18 | 19 | ```csharp 20 | Func multiplyTwoNumbers = (a, b) => a * b; 21 | // Returns 35 22 | int result = multiplyTwoNumbers(7, 5); 23 | ``` 24 | 25 | We won't be using multi-parameter lambda expressions much in this course 26 | 27 | ## Return value 28 | Notice also that there is no `return` statement. Single-line lambda expressions don't need to explicitly use the `return` keyword to return a value. This same thing could also be written as: 29 | 30 | ```csharp 31 | Func multiplyByFive = num => 32 | { 33 | int product = num * 5; 34 | return product; 35 | }; 36 | // Returns 35 37 | int result = multiplyByFive(7); 38 | ``` 39 | 40 | In this case, since the lambda expression has more than one line, both the `return` keyword and the brackets `{ }` around the statements are requried. 41 | 42 | # Exercise 43 | In this exercise, write a lambda expression that returns the provided value plus one. 44 | 45 | @[Lambda Expressions Exercise]({"stubs": ["Background1/LambdaExpressions1.cs"], "command": "Background1.UnitTest.Exercise1", "project": "exercises"}) 46 | -------------------------------------------------------------------------------- /markdowns/02_Background/02_lambda_expressions.template.md: -------------------------------------------------------------------------------- 1 | # Background Topics - Lambda expressions 2 | 3 | A lambda expression is a convenient way of defining an anonymous (unnamed) function that can be passed around as a variable or as a parameter to a method call. Many LINQ methods take a function (called a **delegate**) as a parameter. Here is an example of what a lambda expression looks like: 4 | 5 | ```csharp 6 | //// EMBED: LinqCourseEmbeddedCode/Background1.cs, Lambda 1 7 | ``` 8 | 9 | The expression `num => num * 5` is a lambda expression. The `=>` operator is called the "lambda operator". In this example, `num` is an input parameter to the anonymous function, and the return value of this function is `num * 5`. So when `multiplyByFive` is called with a parameter of `7`, the result is `7 * 5`, or `35`. 10 | 11 | ## Parameter(s) 12 | Notice that the `num` parameter doesn't explicitly specify a data type. The compiler always infers the data type of lambda expression parameters from context. In this case, the context is that the lambda expression is stored in a variable of type `Func`. This means that it takes an `int` parameter and returns an `int` result. 13 | 14 | You can also create lambda expressions with more than one parameter, as shown here: 15 | 16 | ```csharp 17 | //// EMBED: LinqCourseEmbeddedCode/Background1.cs, Lambda 2 18 | ``` 19 | 20 | We won't be using multi-parameter lambda expressions much in this course 21 | 22 | ## Return value 23 | Notice also that there is no `return` statement. Single-line lambda expressions don't need to explicitly use the `return` keyword to return a value. This same thing could also be written as: 24 | 25 | ```csharp 26 | //// EMBED: LinqCourseEmbeddedCode/Background1.cs, Lambda 3 27 | ``` 28 | 29 | In this case, since the lambda expression has more than one line, both the `return` keyword and the brackets `{ }` around the statements are requried. 30 | 31 | # Exercise 32 | In this exercise, write a lambda expression that returns the provided value plus one. 33 | 34 | @[Lambda Expressions Exercise]({"stubs": ["Background1/LambdaExpressions1.cs"], "command": "Background1.UnitTest.Exercise1", "project": "exercises"}) 35 | -------------------------------------------------------------------------------- /markdowns/02_Background/03_ienumerable.md: -------------------------------------------------------------------------------- 1 | [//]: # (GENERATED FILE -- DO NOT EDIT) 2 | # Background Topics - IEnumerable<T> 3 | 4 | The `IEnumerable` interface is central to LINQ. All LINQ methods are extension methods to the `IEnumerable` interface. That means that you can call **any** LINQ method on **any** object that implements `IEnumerable`. You can even create your own classes that implement `IEnumerable`, and those classes will instantly "inherit" all LINQ functionality! 5 | 6 | Pretty cool huh? 7 | 8 | ## What is IEnumerable<T>? 9 | `IEnumerable` is an interface that guarantees a given class is **iterable**. That's a technical term indicating a class that implements `IEnumerable` can be thought of and used as a sequence of elements. 10 | 11 | ## What classes implement IEnumerable<T>? 12 | Most C# **collections** and all C# **arrays** implement `IEnumerable`. Here are some examples: 13 | 14 | ```csharp 15 | IEnumerable list = new List { 1, 2, 3 }; 16 | IEnumerable array = new[] { 1, 2, 3 }; 17 | IEnumerable set = new SortedSet { 1, 2, 3 }; 18 | ``` 19 | 20 | ## What's the <T>? 21 | A `` after an interface name indicates that the interface is **generic**. This means that it can be used with any data type, and the `T` is a placeholder for that data type. In the case of `IEnumerable`, the `T` represents the data type of the elements within the sequence. 22 | 23 | An `IEnumerable` contains a sequence of `int`s. An `IEnumerable` contains a sequence of `string`s. An `IEnumerable` contains (God help us) a sequence of `object`s, meaning it can hold, quite literally, anything. 24 | -------------------------------------------------------------------------------- /markdowns/02_Background/03_ienumerable.template.md: -------------------------------------------------------------------------------- 1 | # Background Topics - IEnumerable<T> 2 | 3 | The `IEnumerable` interface is central to LINQ. All LINQ methods are extension methods to the `IEnumerable` interface. That means that you can call **any** LINQ method on **any** object that implements `IEnumerable`. You can even create your own classes that implement `IEnumerable`, and those classes will instantly "inherit" all LINQ functionality! 4 | 5 | Pretty cool huh? 6 | 7 | ## What is IEnumerable<T>? 8 | `IEnumerable` is an interface that guarantees a given class is **iterable**. That's a technical term indicating a class that implements `IEnumerable` can be thought of and used as a sequence of elements. 9 | 10 | ## What classes implement IEnumerable<T>? 11 | Most C# **collections** and all C# **arrays** implement `IEnumerable`. Here are some examples: 12 | 13 | ```csharp 14 | //// EMBED: LinqCourseEmbeddedCode/Background1.cs, IEnumerable examples 15 | ``` 16 | 17 | ## What's the <T>? 18 | A `` after an interface name indicates that the interface is **generic**. This means that it can be used with any data type, and the `T` is a placeholder for that data type. In the case of `IEnumerable`, the `T` represents the data type of the elements within the sequence. 19 | 20 | An `IEnumerable` contains a sequence of `int`s. An `IEnumerable` contains a sequence of `string`s. An `IEnumerable` contains (God help us) a sequence of `object`s, meaning it can hold, quite literally, anything. 21 | -------------------------------------------------------------------------------- /markdowns/02_Background/04_to_list_to_array.md: -------------------------------------------------------------------------------- 1 | [//]: # (GENERATED FILE -- DO NOT EDIT) 2 | # Background Topics - ToList() and ToArray() 3 | 4 | Any LINQ method that returns a sequence of elements returns it as an `IEnumerable`. For many applications, it can be difficult to work with this interface, and it may be desirable to **iterate** this enumerable to either a list or an array. Both of these are more intuitive to use. 5 | 6 | LINQ provides two very handy methods to do just this: [`ToList()`](https://msdn.microsoft.com/en-us/library/bb342261%28v=vs.110%29.aspx) and [`ToArray()`](https://msdn.microsoft.com/en-us/library/bb298736%28v=vs.110%29.aspx). The method names are pretty self-explanatory. They "convert" an `IEnumerable` to either a `List` or an array of type `T[]`. 7 | 8 | Here are a few examples: 9 | 10 | ```csharp 11 | List list = new[] {1, 2, 3}.ToList(); 12 | int[] array = new List {1, 2, 3}.ToArray(); 13 | List list2 = new SortedSet {1, 2, 3}.ToList(); 14 | ``` 15 | -------------------------------------------------------------------------------- /markdowns/02_Background/04_to_list_to_array.template.md: -------------------------------------------------------------------------------- 1 | # Background Topics - ToList() and ToArray() 2 | 3 | Any LINQ method that returns a sequence of elements returns it as an `IEnumerable`. For many applications, it can be difficult to work with this interface, and it may be desirable to **iterate** this enumerable to either a list or an array. Both of these are more intuitive to use. 4 | 5 | LINQ provides two very handy methods to do just this: [`ToList()`](https://msdn.microsoft.com/en-us/library/bb342261%28v=vs.110%29.aspx) and [`ToArray()`](https://msdn.microsoft.com/en-us/library/bb298736%28v=vs.110%29.aspx). The method names are pretty self-explanatory. They "convert" an `IEnumerable` to either a `List` or an array of type `T[]`. 6 | 7 | Here are a few examples: 8 | 9 | ```csharp 10 | //// EMBED: LinqCourseEmbeddedCode/Background1.cs, ToList() and ToArray() 11 | ``` 12 | -------------------------------------------------------------------------------- /markdowns/03_LinqConcepts/01_concepts_intro.md: -------------------------------------------------------------------------------- 1 | [//]: # (GENERATED FILE -- DO NOT EDIT) 2 | # LINQ Concepts - Using LINQ 3 | 4 | LINQ is a collection of extension methods that extend the `IEnumerable` interface, as discussed in the Background lessons. There are around 50 unique methods currently available in LINQ (even more if you count different signature variations as separate methods)! The complete list can be found here: 5 | 6 | [MSDN Enumerable Methods documentation](https://msdn.microsoft.com/en-us/library/system.linq.enumerable_methods%28v=vs.110%29.aspx) 7 | 8 | Some methods are very simple, such as the `Count()` method. On the other hand, several LINQ methods are very complicated and difficult to understand. The `GroupJoin()` method would be a good example of this. 9 | 10 | ## General method categories 11 | - Some methods return a single element from the target sequence, such as `First()` or `Last()`. 12 | - Some methods return multiple elements out of the target sequence, such as `Take()`, `Skip()`, and `Where()`. 13 | - Some methods return the entire target sequence with the elements' order changed, such as `Reverse()` and `OrderBy()`. 14 | - Some methods return a single calculated value based on the input, such as `Any()`, `Sum()`, and `Max()`. 15 | - Some methods return a completely different sequence based on the target sequence, such as `Select()` and `Cast()`. 16 | 17 | # Categorization quiz 18 | Based on the method name and the signature information in the [MSDN documentation](https://msdn.microsoft.com/en-us/library/system.linq.enumerable_methods%28v=vs.110%29.aspx), try to guess in which of the above categories each method belongs. 19 | 20 | ?[Which category best describes the Count() method?] 21 | - [ ] Single element from the sequence 22 | - [ ] Multiple elements from the sequence 23 | - [ ] Change the order of the elements 24 | - [x] Single calculated value based on the input 25 | - [ ] Different sequence based on the input 26 | 27 | ?[Which category best describes the Intersect() method?] 28 | - [ ] Single element from the sequence 29 | - [x] Multiple elements from the sequence 30 | - [ ] Change the order of the elements 31 | - [ ] Single calculated value based on the input 32 | - [ ] Different sequence based on the input 33 | 34 | ?[Which category best describes the SelectMany() method?] 35 | - [ ] Single element from the sequence 36 | - [ ] Multiple elements from the sequence 37 | - [ ] Change the order of the elements 38 | - [ ] Single calculated value based on the input 39 | - [x] Different sequence based on the input 40 | 41 | ?[Which category best describes the ElementAt() method?] 42 | - [x] Single element from the sequence 43 | - [ ] Multiple elements from the sequence 44 | - [ ] Change the order of the elements 45 | - [ ] Single calculated value based on the input 46 | - [ ] Different sequence based on the input 47 | -------------------------------------------------------------------------------- /markdowns/03_LinqConcepts/01_concepts_intro.template.md: -------------------------------------------------------------------------------- 1 | # LINQ Concepts - Using LINQ 2 | 3 | LINQ is a collection of extension methods that extend the `IEnumerable` interface, as discussed in the Background lessons. There are around 50 unique methods currently available in LINQ (even more if you count different signature variations as separate methods)! The complete list can be found here: 4 | 5 | [MSDN Enumerable Methods documentation](https://msdn.microsoft.com/en-us/library/system.linq.enumerable_methods%28v=vs.110%29.aspx) 6 | 7 | Some methods are very simple, such as the `Count()` method. On the other hand, several LINQ methods are very complicated and difficult to understand. The `GroupJoin()` method would be a good example of this. 8 | 9 | ## General method categories 10 | - Some methods return a single element from the target sequence, such as `First()` or `Last()`. 11 | - Some methods return multiple elements out of the target sequence, such as `Take()`, `Skip()`, and `Where()`. 12 | - Some methods return the entire target sequence with the elements' order changed, such as `Reverse()` and `OrderBy()`. 13 | - Some methods return a single calculated value based on the input, such as `Any()`, `Sum()`, and `Max()`. 14 | - Some methods return a completely different sequence based on the target sequence, such as `Select()` and `Cast()`. 15 | 16 | # Categorization quiz 17 | Based on the method name and the signature information in the [MSDN documentation](https://msdn.microsoft.com/en-us/library/system.linq.enumerable_methods%28v=vs.110%29.aspx), try to guess in which of the above categories each method belongs. 18 | 19 | ?[Which category best describes the Count() method?] 20 | - [ ] Single element from the sequence 21 | - [ ] Multiple elements from the sequence 22 | - [ ] Change the order of the elements 23 | - [x] Single calculated value based on the input 24 | - [ ] Different sequence based on the input 25 | 26 | ?[Which category best describes the Intersect() method?] 27 | - [ ] Single element from the sequence 28 | - [x] Multiple elements from the sequence 29 | - [ ] Change the order of the elements 30 | - [ ] Single calculated value based on the input 31 | - [ ] Different sequence based on the input 32 | 33 | ?[Which category best describes the SelectMany() method?] 34 | - [ ] Single element from the sequence 35 | - [ ] Multiple elements from the sequence 36 | - [ ] Change the order of the elements 37 | - [ ] Single calculated value based on the input 38 | - [x] Different sequence based on the input 39 | 40 | ?[Which category best describes the ElementAt() method?] 41 | - [x] Single element from the sequence 42 | - [ ] Multiple elements from the sequence 43 | - [ ] Change the order of the elements 44 | - [ ] Single calculated value based on the input 45 | - [ ] Different sequence based on the input 46 | -------------------------------------------------------------------------------- /markdowns/03_LinqConcepts/02_query_syntax.md: -------------------------------------------------------------------------------- 1 | [//]: # (GENERATED FILE -- DO NOT EDIT) 2 | # LINQ Concepts - Query syntax 3 | 4 | There are two different syntax paradigms for accessing LINQ functionality: **query syntax** and **method syntax**. 5 | 6 | Query syntax has a very distinctive syntactical style. Due to its unique format, query syntax is very memorable and somewhat iconic as it's often what people envision when thinking of LINQ. Here is an example of LINQ code using query syntax: 7 | 8 | ## Query syntax example 9 | ```csharp 10 | using System.Linq; 11 | 12 | ... 13 | 14 | List animalNames = new List 15 | {"fawn", "gibbon", "heron", "ibex", "jackalope"}; 16 | 17 | // Result: {"heron", "gibbon", "jackalope"} 18 | IEnumerable longAnimalNames = 19 | from name in animalNames 20 | where name.Length >= 5 21 | orderby name.Length 22 | select name; 23 | ``` 24 | 25 | For those who are familiar with SQL syntax, you might find some similarities in this example. It's not exactly the same as SQL though. This example gathers all the strings in `animalNames` that are at least 5 characters in length, ordered from the entry with the fewest characters to the entry with the most characters. 26 | 27 | > **NOTE:** The above example includes `using System.Linq;`. This is **essential** when using LINQ. Both query syntax and method syntax require it. Although I will not include it in all examples, it is always implied. 28 | 29 | ## Advantages of query syntax 30 | 31 | - The [MSDN documentation](https://msdn.microsoft.com/en-us/library/bb397947.aspx) claims that "*many people find query syntax simpler and easier to read*." 32 | - Query syntax can be more compact since the variables created have a scope that spans the whole statement, vs. method syntax where variables need to be re-declared for each method call. 33 | 34 | 35 | ## Insane query syntax example 36 | Here is an example of the expressiveness of LINQ query syntax: 37 | 38 | [Taking LINQ to Objects to Extremes: A fully LINQified RayTracer](https://blogs.msdn.microsoft.com/lukeh/2007/10/01/taking-linq-to-objects-to-extremes-a-fully-linqified-raytracer/) 39 | 40 | Try to decipher that, I challenge you! 41 | 42 | # Query syntax exercise 43 | 44 | Now you try it out. The following code shows a LINQ query that returns the input `inValues` unmodified. Using the format of the example above, see if you can return only the strings that have `pattern` in them (using the [`String.Contains()`](https://msdn.microsoft.com/en-us/library/dy85x1sa%28v=vs.110%29.aspx) method) and order the list alphabetically. 45 | 46 | @[Query Syntax Exercise]({"stubs": ["QuerySyntax1/QuerySyntax1.cs"], "command": "QuerySyntax1.UnitTest.Exercise1", "project": "exercises"}) 47 | -------------------------------------------------------------------------------- /markdowns/03_LinqConcepts/02_query_syntax.template.md: -------------------------------------------------------------------------------- 1 | # LINQ Concepts - Query syntax 2 | 3 | There are two different syntax paradigms for accessing LINQ functionality: **query syntax** and **method syntax**. 4 | 5 | Query syntax has a very distinctive syntactical style. Due to its unique format, query syntax is very memorable and somewhat iconic as it's often what people envision when thinking of LINQ. Here is an example of LINQ code using query syntax: 6 | 7 | ## Query syntax example 8 | ```csharp 9 | //// EMBED: LinqCourseEmbeddedCode/LinqConcepts1.cs, using System.Linq 10 | 11 | ... 12 | 13 | //// EMBED: LinqCourseEmbeddedCode/LinqConcepts1.cs, LINQ query syntax 14 | ``` 15 | 16 | For those who are familiar with SQL syntax, you might find some similarities in this example. It's not exactly the same as SQL though. This example gathers all the strings in `animalNames` that are at least 5 characters in length, ordered from the entry with the fewest characters to the entry with the most characters. 17 | 18 | > **NOTE:** The above example includes `using System.Linq;`. This is **essential** when using LINQ. Both query syntax and method syntax require it. Although I will not include it in all examples, it is always implied. 19 | 20 | ## Advantages of query syntax 21 | 22 | - The [MSDN documentation](https://msdn.microsoft.com/en-us/library/bb397947.aspx) claims that "*many people find query syntax simpler and easier to read*." 23 | - Query syntax can be more compact since the variables created have a scope that spans the whole statement, vs. method syntax where variables need to be re-declared for each method call. 24 | 25 | 26 | ## Insane query syntax example 27 | Here is an example of the expressiveness of LINQ query syntax: 28 | 29 | [Taking LINQ to Objects to Extremes: A fully LINQified RayTracer](https://blogs.msdn.microsoft.com/lukeh/2007/10/01/taking-linq-to-objects-to-extremes-a-fully-linqified-raytracer/) 30 | 31 | Try to decipher that, I challenge you! 32 | 33 | # Query syntax exercise 34 | 35 | Now you try it out. The following code shows a LINQ query that returns the input `inValues` unmodified. Using the format of the example above, see if you can return only the strings that have `pattern` in them (using the [`String.Contains()`](https://msdn.microsoft.com/en-us/library/dy85x1sa%28v=vs.110%29.aspx) method) and order the list alphabetically. 36 | 37 | @[Query Syntax Exercise]({"stubs": ["QuerySyntax1/QuerySyntax1.cs"], "command": "QuerySyntax1.UnitTest.Exercise1", "project": "exercises"}) 38 | -------------------------------------------------------------------------------- /markdowns/03_LinqConcepts/03_method_syntax.md: -------------------------------------------------------------------------------- 1 | [//]: # (GENERATED FILE -- DO NOT EDIT) 2 | # LINQ Concepts - Method syntax 3 | The other LINQ format is method syntax. LINQ method syntax can do everything that query syntax can do, and more. It's just a different way to format the instructions. 4 | 5 | ## Method syntax example 6 | Recall this example of query syntax from the previous lesson: 7 | 8 | ```csharp 9 | List animalNames = new List 10 | {"fawn", "gibbon", "heron", "ibex", "jackalope"}; 11 | 12 | // Result: {"heron", "gibbon", "jackalope"} 13 | IEnumerable longAnimalNames = 14 | from name in animalNames 15 | where name.Length >= 5 16 | orderby name.Length 17 | select name; 18 | ``` 19 | 20 | The exact same instruction set can be written using method syntax like this: 21 | 22 | ```csharp 23 | List animalNames = new List 24 | {"fawn", "gibbon", "heron", "ibex", "jackalope"}; 25 | 26 | IEnumerable longAnimalNames = 27 | animalNames 28 | .Where(name => name.Length >= 5) 29 | .OrderBy(name => name.Length); 30 | ``` 31 | 32 | > **NOTE:** The spaces, tabs, and linebreaks in these examples are just whitespace, used for formatting, and are not syntactically important. 33 | 34 | ## Advantages of method syntax 35 | 36 | Personally, I prefer method syntax over query syntax, and this is the format that will be used for the rest of this course. Here are some of the advantages of method syntax: 37 | 38 | - Query syntax is automatically converted to method syntax at compilation time 39 | - Not all LINQ methods can be utilized with query syntax 40 | - Method syntax is stylistically more similar to other C# code 41 | 42 | # Method syntax exercise 43 | 44 | This is the exact same exercise as in the previous lesson. Now try to write it with method syntax. 45 | 46 | The following code shows a LINQ query that returns the input `inValues` unmodified. Using the format of the example above, see if you can return only the strings that have `pattern` in them (using the [`String.Contains()`](https://msdn.microsoft.com/en-us/library/dy85x1sa%28v=vs.110%29.aspx) method) and order the list alphabetically. 47 | 48 | @[Method Syntax Exercise]({"stubs": ["MethodSyntax1/MethodSyntax1.cs"], "command": "MethodSyntax1.UnitTest.Exercise1", "project": "exercises"}) 49 | -------------------------------------------------------------------------------- /markdowns/03_LinqConcepts/03_method_syntax.template.md: -------------------------------------------------------------------------------- 1 | # LINQ Concepts - Method syntax 2 | The other LINQ format is method syntax. LINQ method syntax can do everything that query syntax can do, and more. It's just a different way to format the instructions. 3 | 4 | ## Method syntax example 5 | Recall this example of query syntax from the previous lesson: 6 | 7 | ```csharp 8 | //// EMBED: LinqCourseEmbeddedCode/LinqConcepts1.cs, LINQ query syntax 9 | ``` 10 | 11 | The exact same instruction set can be written using method syntax like this: 12 | 13 | ```csharp 14 | //// EMBED: LinqCourseEmbeddedCode/LinqConcepts1.cs, LINQ method syntax 15 | ``` 16 | 17 | > **NOTE:** The spaces, tabs, and linebreaks in these examples are just whitespace, used for formatting, and are not syntactically important. 18 | 19 | ## Advantages of method syntax 20 | 21 | Personally, I prefer method syntax over query syntax, and this is the format that will be used for the rest of this course. Here are some of the advantages of method syntax: 22 | 23 | - Query syntax is automatically converted to method syntax at compilation time 24 | - Not all LINQ methods can be utilized with query syntax 25 | - Method syntax is stylistically more similar to other C# code 26 | 27 | # Method syntax exercise 28 | 29 | This is the exact same exercise as in the previous lesson. Now try to write it with method syntax. 30 | 31 | The following code shows a LINQ query that returns the input `inValues` unmodified. Using the format of the example above, see if you can return only the strings that have `pattern` in them (using the [`String.Contains()`](https://msdn.microsoft.com/en-us/library/dy85x1sa%28v=vs.110%29.aspx) method) and order the list alphabetically. 32 | 33 | @[Method Syntax Exercise]({"stubs": ["MethodSyntax1/MethodSyntax1.cs"], "command": "MethodSyntax1.UnitTest.Exercise1", "project": "exercises"}) 34 | -------------------------------------------------------------------------------- /markdowns/04_MethodsExtractAValue/01_first_last_single.md: -------------------------------------------------------------------------------- 1 | [//]: # (GENERATED FILE -- DO NOT EDIT) 2 | # Methods - Extract a single element 3 | 4 | These LINQ methods can be used to extract a single element from an `IEnumerable` sequence. 5 | 6 | > **NOTE:** All four of the methods in this lesson throw an exception if they can't find an appropriate element to return. Only use them if you are absolutely certain that an element exists for them to return. You could `catch` the exception (and probably should to handle true error conditions) but if you expect that these may reasonably fail, you should use the `OrDefault` variants instead. We will go over those methods in a later lesson. 7 | 8 | # [First()](https://msdn.microsoft.com/en-us/library/bb291976%28v=vs.110%29.aspx) method 9 | Intuitively enough, this extracts the first element in the sequence. The data type of the value returned depends on the type of `T` in the `IEnumerable` that the method is invoked on. If it is a sequence of `int`, then `First()` will return an `int`. 10 | 11 | For example: 12 | 13 | ```csharp 14 | List doubles = new List { 2.0, 2.1, 2.2, 2.3 }; 15 | double whatsThis = doubles.First(); 16 | ``` 17 | 18 | Looking at this code, what do you think the `First()` method call would return? 19 | 20 | ?[What is the value of the whatsThis variable?] 21 | - [ ] 2.2 22 | - [x] 2.0 23 | - [ ] Nothing. The First() call would throw an Exception. 24 | - [ ] 2.3 25 | 26 | # [Last()](https://msdn.microsoft.com/en-us/library/bb358775%28v=vs.110%29.aspx) method 27 | Hmm.... What do you think the `Last()` in this code would return? 28 | 29 | ```csharp 30 | List doubles = new List { 2.0, 2.1, 2.2, 2.3 }; 31 | double whatsThis = doubles.Last(); 32 | ``` 33 | 34 | ?[What is the value of the whatsThis variable?] 35 | - [ ] 2.2 36 | - [ ] 2.0 37 | - [ ] Nothing. The Last() call would throw an Exception. 38 | - [x] 2.3 39 | 40 | # [ElementAt()](https://msdn.microsoft.com/en-us/library/bb299233%28v=vs.110%29.aspx) method 41 | Try this one. What would the `ElementAt(2)` call return in this code snippet? 42 | 43 | ```csharp 44 | List doubles = new List { 2.0, 2.1, 2.2, 2.3 }; 45 | double whatsThis = doubles.ElementAt(2); 46 | ``` 47 | 48 | ?[What is the value of the whatsThis variable?] 49 | - [x] 2.2 50 | - [ ] 2.0 51 | - [ ] Nothing. The ElementAt() call would throw an Exception. 52 | - [ ] 2.3 53 | 54 | # [Single()](https://msdn.microsoft.com/en-us/library/bb155325%28v=vs.110%29.aspx) method 55 | `Single()` is an interesting method. You call it when you are expecting that there is only a single element in the sequence. If there is more than one element, or if there are no elements, then `Single()` will throw an exception. 56 | 57 | With this in mind, what do you think this would return? 58 | 59 | ```csharp 60 | List doubles = new List { 2.0, 2.1, 2.2, 2.3 }; 61 | double whatsThis = doubles.Single(); 62 | ``` 63 | 64 | ?[What is the value of the whatsThis variable?] 65 | - [ ] 2.2 66 | - [ ] 2.0 67 | - [x] Nothing. The Single() call would throw an Exception. 68 | - [ ] 2.3 69 | -------------------------------------------------------------------------------- /markdowns/04_MethodsExtractAValue/01_first_last_single.template.md: -------------------------------------------------------------------------------- 1 | # Methods - Extract a single element 2 | 3 | These LINQ methods can be used to extract a single element from an `IEnumerable` sequence. 4 | 5 | > **NOTE:** All four of the methods in this lesson throw an exception if they can't find an appropriate element to return. Only use them if you are absolutely certain that an element exists for them to return. You could `catch` the exception (and probably should to handle true error conditions) but if you expect that these may reasonably fail, you should use the `OrDefault` variants instead. We will go over those methods in a later lesson. 6 | 7 | # [First()](https://msdn.microsoft.com/en-us/library/bb291976%28v=vs.110%29.aspx) method 8 | Intuitively enough, this extracts the first element in the sequence. The data type of the value returned depends on the type of `T` in the `IEnumerable` that the method is invoked on. If it is a sequence of `int`, then `First()` will return an `int`. 9 | 10 | For example: 11 | 12 | ```csharp 13 | //// EMBED: LinqCourseEmbeddedCode/Methods1.cs, First() 14 | ``` 15 | 16 | Looking at this code, what do you think the `First()` method call would return? 17 | 18 | ?[What is the value of the whatsThis variable?] 19 | - [ ] 2.2 20 | - [x] 2.0 21 | - [ ] Nothing. The First() call would throw an Exception. 22 | - [ ] 2.3 23 | 24 | # [Last()](https://msdn.microsoft.com/en-us/library/bb358775%28v=vs.110%29.aspx) method 25 | Hmm.... What do you think the `Last()` in this code would return? 26 | 27 | ```csharp 28 | //// EMBED: LinqCourseEmbeddedCode/Methods1.cs, Last() 29 | ``` 30 | 31 | ?[What is the value of the whatsThis variable?] 32 | - [ ] 2.2 33 | - [ ] 2.0 34 | - [ ] Nothing. The Last() call would throw an Exception. 35 | - [x] 2.3 36 | 37 | # [ElementAt()](https://msdn.microsoft.com/en-us/library/bb299233%28v=vs.110%29.aspx) method 38 | Try this one. What would the `ElementAt(2)` call return in this code snippet? 39 | 40 | ```csharp 41 | //// EMBED: LinqCourseEmbeddedCode/Methods1.cs, ElementAt() 42 | ``` 43 | 44 | ?[What is the value of the whatsThis variable?] 45 | - [x] 2.2 46 | - [ ] 2.0 47 | - [ ] Nothing. The ElementAt() call would throw an Exception. 48 | - [ ] 2.3 49 | 50 | # [Single()](https://msdn.microsoft.com/en-us/library/bb155325%28v=vs.110%29.aspx) method 51 | `Single()` is an interesting method. You call it when you are expecting that there is only a single element in the sequence. If there is more than one element, or if there are no elements, then `Single()` will throw an exception. 52 | 53 | With this in mind, what do you think this would return? 54 | 55 | ```csharp 56 | //// EMBED: LinqCourseEmbeddedCode/Methods1.cs, Single() 57 | ``` 58 | 59 | ?[What is the value of the whatsThis variable?] 60 | - [ ] 2.2 61 | - [ ] 2.0 62 | - [x] Nothing. The Single() call would throw an Exception. 63 | - [ ] 2.3 64 | -------------------------------------------------------------------------------- /markdowns/04_MethodsExtractAValue/02_conditions.md: -------------------------------------------------------------------------------- 1 | [//]: # (GENERATED FILE -- DO NOT EDIT) 2 | # Methods - Conditionally extract a single element 3 | 4 | Three of the four methods in the previous lesson (`First()`, `Last()`, and `Single()`) have another form that accepts a delegate parameter to make them more selective in which element they return. The provided delegate should take a parameter of type `T` and return a `bool` indicating whether or not the provided parameter meets the criteria. 5 | 6 | > **NOTE:** Same remark as in the previous lesson. If these methods can't find an appropriate element to return, they will throw an exception. 7 | 8 | # [First(<predicate>)](https://msdn.microsoft.com/en-us/library/bb535050%28v=vs.110%29.aspx) method 9 | Any idea what this call to `First()` would return? 10 | 11 | ```csharp 12 | List doubles = new List { 2.0, 2.1, 2.2, 2.3 }; 13 | double whatsThis = doubles.First(val => val > 2.3); 14 | ``` 15 | 16 | ?[What is the value of the whatsThis variable?] 17 | - [ ] 2.2 18 | - [ ] 2.0 19 | - [x] Nothing. The First() call would throw an Exception. 20 | - [ ] 2.3 21 | 22 | # [Last(<predicate>)](https://msdn.microsoft.com/en-us/library/bb549138%28v=vs.110%29.aspx) method 23 | How about this call to `Last()`? 24 | 25 | ```csharp 26 | List doubles = new List { 2.0, 2.1, 2.2, 2.3 }; 27 | double whatsThis = doubles.Last(val => val < 2.1); 28 | ``` 29 | 30 | ?[What is the value of the whatsThis variable?] 31 | - [ ] 2.2 32 | - [x] 2.0 33 | - [ ] Nothing. The Last() call would throw an Exception. 34 | - [ ] 2.3 35 | 36 | # [Single(<predicate>)](https://msdn.microsoft.com/en-us/library/bb535118%28v=vs.110%29.aspx) method 37 | And this call to `Single()`? 38 | 39 | ```csharp 40 | List doubles = new List { 2.0, 2.1, 2.2, 2.3 }; 41 | double whatsThis = doubles.Single(val => val > 2.2); 42 | ``` 43 | 44 | ?[What is the value of the whatsThis variable?] 45 | - [ ] 2.2 46 | - [ ] 2.0 47 | - [ ] Nothing. The Single() call would throw an Exception. 48 | - [x] 2.3 49 | -------------------------------------------------------------------------------- /markdowns/04_MethodsExtractAValue/02_conditions.template.md: -------------------------------------------------------------------------------- 1 | # Methods - Conditionally extract a single element 2 | 3 | Three of the four methods in the previous lesson (`First()`, `Last()`, and `Single()`) have another form that accepts a delegate parameter to make them more selective in which element they return. The provided delegate should take a parameter of type `T` and return a `bool` indicating whether or not the provided parameter meets the criteria. 4 | 5 | > **NOTE:** Same remark as in the previous lesson. If these methods can't find an appropriate element to return, they will throw an exception. 6 | 7 | # [First(<predicate>)](https://msdn.microsoft.com/en-us/library/bb535050%28v=vs.110%29.aspx) method 8 | Any idea what this call to `First()` would return? 9 | 10 | ```csharp 11 | //// EMBED: LinqCourseEmbeddedCode/Methods1.cs, First() - condition 12 | ``` 13 | 14 | ?[What is the value of the whatsThis variable?] 15 | - [ ] 2.2 16 | - [ ] 2.0 17 | - [x] Nothing. The First() call would throw an Exception. 18 | - [ ] 2.3 19 | 20 | # [Last(<predicate>)](https://msdn.microsoft.com/en-us/library/bb549138%28v=vs.110%29.aspx) method 21 | How about this call to `Last()`? 22 | 23 | ```csharp 24 | //// EMBED: LinqCourseEmbeddedCode/Methods1.cs, Last() - condition 25 | ``` 26 | 27 | ?[What is the value of the whatsThis variable?] 28 | - [ ] 2.2 29 | - [x] 2.0 30 | - [ ] Nothing. The Last() call would throw an Exception. 31 | - [ ] 2.3 32 | 33 | # [Single(<predicate>)](https://msdn.microsoft.com/en-us/library/bb535118%28v=vs.110%29.aspx) method 34 | And this call to `Single()`? 35 | 36 | ```csharp 37 | //// EMBED: LinqCourseEmbeddedCode/Methods1.cs, Single() - condition 38 | ``` 39 | 40 | ?[What is the value of the whatsThis variable?] 41 | - [ ] 2.2 42 | - [ ] 2.0 43 | - [ ] Nothing. The Single() call would throw an Exception. 44 | - [x] 2.3 45 | -------------------------------------------------------------------------------- /markdowns/04_MethodsExtractAValue/03_or_default.md: -------------------------------------------------------------------------------- 1 | [//]: # (GENERATED FILE -- DO NOT EDIT) 2 | # Methods - Extract a single element or default 3 | 4 | The previous two lessons had a note explaining that the `First()`, `Last()`, etc. methods would throw an exception if they couldn't return an element. The methods shown here don't throw an exception. They instead return a default value. 5 | 6 | What value do they return? That depends on the type (`T`) of the `IEnumerable` sequence. If `T` is a reference type (a class), then the default value is always `null`. If it is a struct, then the default value is an instance of that struct with all its elements set to their default values. 7 | 8 | For all other data types, there is a [table of default values available on MSDN](https://msdn.microsoft.com/en-us/library/83fhsxwc.aspx). 9 | 10 | # [FirstOrDefault()](https://msdn.microsoft.com/en-us/library/bb340482%28v=vs.110%29.aspx) method 11 | What do you think this call to `FirstOrDefault()` would return? 12 | 13 | ```csharp 14 | List doubles = new List { 2.0, 2.1, 2.2, 2.3 }; 15 | double whatsThis = doubles.FirstOrDefault(val => val > 2.3); 16 | ``` 17 | 18 | ?[What is the value of the whatsThis variable?] 19 | - [x] The default value for double: 0.0D 20 | - [ ] 2.2 21 | - [ ] Nothing. The FirstOrDefault() call would throw an Exception. 22 | - [ ] 2.3 23 | 24 | # [LastOrDefault()](https://msdn.microsoft.com/en-us/library/bb301849%28v=vs.110%29.aspx) method 25 | What do you think the `LastOrDefault()` in this code would return? 26 | 27 | ```csharp 28 | List doubles = new List { 2.0, 2.1, 2.2, 2.3 }; 29 | double whatsThis = doubles.LastOrDefault(val => val > 2.0 && val < 2.3); 30 | ``` 31 | 32 | ?[What is the value of the whatsThis variable?] 33 | - [ ] The default value for double: 0.0D 34 | - [x] 2.2 35 | - [ ] Nothing. The LastOrDefault() call would throw an Exception. 36 | - [ ] 2.3 37 | 38 | # [ElementAtOrDefault()](https://msdn.microsoft.com/en-us/library/bb494386%28v=vs.110%29.aspx) method 39 | Try this one. What would the `ElementAtOrDefault()` call return in this code snippet? 40 | 41 | ```csharp 42 | List doubles = new List { 2.0, 2.1, 2.2, 2.3 }; 43 | double whatsThis = doubles.ElementAtOrDefault(4); 44 | ``` 45 | 46 | ?[What is the value of the whatsThis variable?] 47 | - [x] The default value for double: 0.0D 48 | - [ ] 2.2 49 | - [ ] Nothing. The ElementAtOrDefault() call would throw an Exception. 50 | - [ ] 2.3 51 | 52 | # [SingleOrDefault()](https://msdn.microsoft.com/en-us/library/bb342451%28v=vs.110%29.aspx) method 53 | `SingleOrDefault()` is a bit different from the others. If there is no element in the list that meets the criteria, then a default value is returned. If more than one value meets the criteria, then `SingleOrDefault()` still throws an exception, just like the `Single()` method. 54 | 55 | With this in mind, what do you think this would do? 56 | 57 | ```csharp 58 | List doubles = new List { 2.0, 2.1, 2.2, 2.3 }; 59 | double whatsThis = doubles.SingleOrDefault(val => val > 2.1 && val <= 2.3); 60 | ``` 61 | 62 | ?[What is the value of the whatsThis variable?] 63 | - [ ] The default value for double: 0.0D 64 | - [ ] 2.2 65 | - [x] Nothing. The SingleOrDefault() call would throw an Exception. 66 | - [ ] 2.3 67 | -------------------------------------------------------------------------------- /markdowns/04_MethodsExtractAValue/03_or_default.template.md: -------------------------------------------------------------------------------- 1 | # Methods - Extract a single element or default 2 | 3 | The previous two lessons had a note explaining that the `First()`, `Last()`, etc. methods would throw an exception if they couldn't return an element. The methods shown here don't throw an exception. They instead return a default value. 4 | 5 | What value do they return? That depends on the type (`T`) of the `IEnumerable` sequence. If `T` is a reference type (a class), then the default value is always `null`. If it is a struct, then the default value is an instance of that struct with all its elements set to their default values. 6 | 7 | For all other data types, there is a [table of default values available on MSDN](https://msdn.microsoft.com/en-us/library/83fhsxwc.aspx). 8 | 9 | # [FirstOrDefault()](https://msdn.microsoft.com/en-us/library/bb340482%28v=vs.110%29.aspx) method 10 | What do you think this call to `FirstOrDefault()` would return? 11 | 12 | ```csharp 13 | //// EMBED: LinqCourseEmbeddedCode/Methods1.cs, FirstOrDefault() 14 | ``` 15 | 16 | ?[What is the value of the whatsThis variable?] 17 | - [x] The default value for double: 0.0D 18 | - [ ] 2.2 19 | - [ ] Nothing. The FirstOrDefault() call would throw an Exception. 20 | - [ ] 2.3 21 | 22 | # [LastOrDefault()](https://msdn.microsoft.com/en-us/library/bb301849%28v=vs.110%29.aspx) method 23 | What do you think the `LastOrDefault()` in this code would return? 24 | 25 | ```csharp 26 | //// EMBED: LinqCourseEmbeddedCode/Methods1.cs, LastOrDefault() 27 | ``` 28 | 29 | ?[What is the value of the whatsThis variable?] 30 | - [ ] The default value for double: 0.0D 31 | - [x] 2.2 32 | - [ ] Nothing. The LastOrDefault() call would throw an Exception. 33 | - [ ] 2.3 34 | 35 | # [ElementAtOrDefault()](https://msdn.microsoft.com/en-us/library/bb494386%28v=vs.110%29.aspx) method 36 | Try this one. What would the `ElementAtOrDefault()` call return in this code snippet? 37 | 38 | ```csharp 39 | //// EMBED: LinqCourseEmbeddedCode/Methods1.cs, ElementAtOrDefault() 40 | ``` 41 | 42 | ?[What is the value of the whatsThis variable?] 43 | - [x] The default value for double: 0.0D 44 | - [ ] 2.2 45 | - [ ] Nothing. The ElementAtOrDefault() call would throw an Exception. 46 | - [ ] 2.3 47 | 48 | # [SingleOrDefault()](https://msdn.microsoft.com/en-us/library/bb342451%28v=vs.110%29.aspx) method 49 | `SingleOrDefault()` is a bit different from the others. If there is no element in the list that meets the criteria, then a default value is returned. If more than one value meets the criteria, then `SingleOrDefault()` still throws an exception, just like the `Single()` method. 50 | 51 | With this in mind, what do you think this would do? 52 | 53 | ```csharp 54 | //// EMBED: LinqCourseEmbeddedCode/Methods1.cs, SingleOrDefault() 55 | ``` 56 | 57 | ?[What is the value of the whatsThis variable?] 58 | - [ ] The default value for double: 0.0D 59 | - [ ] 2.2 60 | - [x] Nothing. The SingleOrDefault() call would throw an Exception. 61 | - [ ] 2.3 62 | -------------------------------------------------------------------------------- /markdowns/04_MethodsExtractAValue/04_single_value_exercise.md: -------------------------------------------------------------------------------- 1 | [//]: # (GENERATED FILE -- DO NOT EDIT) 2 | # Exercise - Extract a single element 3 | 4 | Using what you have learned about `First()`, `Last()`, `ElementAt()`, and `Single()` (and their variations) modify the methods in this exercise to extract the desired element from the provided sequence of strings. 5 | 6 | For reference, here are some examples of LINQ methods that return a single element from the sequence: 7 | 8 | ```csharp 9 | List doubles = new List { 2.0, 2.1, 2.2, 2.3 }; 10 | double whatsThis = doubles.First(); 11 | 12 | List doubles = new List { 2.0, 2.1, 2.2, 2.3 }; 13 | double whatsThis = doubles.Last(val => val < 2.1); 14 | 15 | 16 | List doubles = new List { 2.0, 2.1, 2.2, 2.3 }; 17 | double whatsThis = doubles.ElementAtOrDefault(4); 18 | ``` 19 | 20 | @[Extract a Single Value Exercise]({"stubs": ["SingleValue1/SingleValue1.cs"], "command": "SingleValue1.UnitTest.Exercise1", "project": "exercises"}) 21 | -------------------------------------------------------------------------------- /markdowns/04_MethodsExtractAValue/04_single_value_exercise.template.md: -------------------------------------------------------------------------------- 1 | # Exercise - Extract a single element 2 | 3 | Using what you have learned about `First()`, `Last()`, `ElementAt()`, and `Single()` (and their variations) modify the methods in this exercise to extract the desired element from the provided sequence of strings. 4 | 5 | For reference, here are some examples of LINQ methods that return a single element from the sequence: 6 | 7 | ```csharp 8 | //// EMBED: LinqCourseEmbeddedCode/Methods1.cs, First() 9 | 10 | //// EMBED: LinqCourseEmbeddedCode/Methods1.cs, Last() - condition 11 | 12 | 13 | //// EMBED: LinqCourseEmbeddedCode/Methods1.cs, ElementAtOrDefault() 14 | ``` 15 | 16 | @[Extract a Single Value Exercise]({"stubs": ["SingleValue1/SingleValue1.cs"], "command": "SingleValue1.UnitTest.Exercise1", "project": "exercises"}) 17 | -------------------------------------------------------------------------------- /markdowns/05_MethodsExtractValues/01_skip_take.md: -------------------------------------------------------------------------------- 1 | [//]: # (GENERATED FILE -- DO NOT EDIT) 2 | # Methods - Extract multiple elements 3 | 4 | These LINQ methods can be used to extract multiple elements from an `IEnumerable` sequence. Each method in this chapter provides a different means of defining the criteria determining which sequence elements to remove and which elements to keep. 5 | 6 | > **NOTE:** Throughout this chapter, I state that a method "returns a sequence". This is not technically true. The methods in this chapter return an `IEnumerable`, which is a generator (or an iterator) that can provide a sequence on demand. The difference is subtle, and can often be ignored, but there are some situations where the distinction is important. These special cases will be discussed in more detail in the **Advanced Topics** course. 7 | 8 | # [Take()](https://msdn.microsoft.com/en-us/library/bb503062%28v=vs.110%29.aspx) method 9 | The `Take()` method extracts the first `n` elements (where `n` is a parameter to the method) from the beginning of the target sequence and returns a new sequence containing only the elements taken. 10 | 11 | ```csharp 12 | List bools = new List { true, false, true, true, false }; 13 | // Will contain { true, false, true } 14 | IEnumerable result = bools.Take(3); 15 | ``` 16 | 17 | # [Skip()](https://msdn.microsoft.com/en-us/library/bb358985%28v=vs.110%29.aspx) method 18 | The `Skip()` method can be thought of as the exact opposite of the `Take()` method. Where the `Take()` method, returns a sequence containing the first `n` elements of the target sequence, the `Skip()` method "skips" over the first `n` elements in the sequence and returns a new sequence containing the remaining elements after the first `n` elements. 19 | 20 | ```csharp 21 | List bools = new List { true, false, true, true, false }; 22 | // Will contain { true, true, false } 23 | IEnumerable result = bools.Skip(2); 24 | ``` 25 | 26 | # Exercise 27 | In this exercise, make the `GetThirdFourthFifthItems()` method return the 3rd, 4th, and 5th elements of the provided sequence. 28 | 29 | @[Take and Skip Exercise]({"stubs": ["MultipleValue1/SkipTake1.cs"], "command": "MultipleValue1.UnitTest.Exercise1", "project": "exercises"}) 30 | -------------------------------------------------------------------------------- /markdowns/05_MethodsExtractValues/01_skip_take.template.md: -------------------------------------------------------------------------------- 1 | # Methods - Extract multiple elements 2 | 3 | These LINQ methods can be used to extract multiple elements from an `IEnumerable` sequence. Each method in this chapter provides a different means of defining the criteria determining which sequence elements to remove and which elements to keep. 4 | 5 | > **NOTE:** Throughout this chapter, I state that a method "returns a sequence". This is not technically true. The methods in this chapter return an `IEnumerable`, which is a generator (or an iterator) that can provide a sequence on demand. The difference is subtle, and can often be ignored, but there are some situations where the distinction is important. These special cases will be discussed in more detail in the **Advanced Topics** course. 6 | 7 | # [Take()](https://msdn.microsoft.com/en-us/library/bb503062%28v=vs.110%29.aspx) method 8 | The `Take()` method extracts the first `n` elements (where `n` is a parameter to the method) from the beginning of the target sequence and returns a new sequence containing only the elements taken. 9 | 10 | ```csharp 11 | //// EMBED: LinqCourseEmbeddedCode/Methods2.cs, Take() 12 | ``` 13 | 14 | # [Skip()](https://msdn.microsoft.com/en-us/library/bb358985%28v=vs.110%29.aspx) method 15 | The `Skip()` method can be thought of as the exact opposite of the `Take()` method. Where the `Take()` method, returns a sequence containing the first `n` elements of the target sequence, the `Skip()` method "skips" over the first `n` elements in the sequence and returns a new sequence containing the remaining elements after the first `n` elements. 16 | 17 | ```csharp 18 | //// EMBED: LinqCourseEmbeddedCode/Methods2.cs, Skip() 19 | ``` 20 | 21 | # Exercise 22 | In this exercise, make the `GetThirdFourthFifthItems()` method return the 3rd, 4th, and 5th elements of the provided sequence. 23 | 24 | @[Take and Skip Exercise]({"stubs": ["MultipleValue1/SkipTake1.cs"], "command": "MultipleValue1.UnitTest.Exercise1", "project": "exercises"}) 25 | -------------------------------------------------------------------------------- /markdowns/05_MethodsExtractValues/02_skip_while_take_while.md: -------------------------------------------------------------------------------- 1 | [//]: # (GENERATED FILE -- DO NOT EDIT) 2 | # Methods - Extract multiple elements 3 | 4 | In the previous lesson, we learned about `Take()` and `Skip()`, both of which accept an integer parameter. Each of these methods also have a variant that utilizes a delegate method to determine which elements will be taken or skipped. 5 | 6 | # [TakeWhile(<predicate>)](https://msdn.microsoft.com/en-us/library/bb534804%28v=vs.110%29.aspx) method 7 | `TakeWhile()` behaves similarly to the `Take()` method except that instead of taking the first `n` elements of a sequence, it "takes" all of the initial elements of a sequence that meet the criteria specified by the **predicate**, and stops on the first element that doesn't meet the criteria. It then returns a new sequence containing all the "taken" elements. 8 | 9 | The **predicate** is passed into `TakeWhile()` as a delegate method that takes a single parameter of type `T` (where `T` is the data type of the elements in the `IEnumerable` sequence) and returns a `bool` indicating whether or not the passed-in element should be "taken". 10 | 11 | ```csharp 12 | List ints = new List { 1, 2, 4, 8, 4, 2, 1 }; 13 | // Will contain { 1, 2, 4 } 14 | IEnumerable result = ints.TakeWhile(theInt => theInt < 5); 15 | ``` 16 | 17 | # [SkipWhile(<predicate>)](https://msdn.microsoft.com/en-us/library/bb549075%28v=vs.110%29.aspx) method 18 | Just as `Skip()` is the spiritual opposite of `Take()`, `SkipWhile()` is the opposite of `TakeWhile()`. `SkipWhile()` "skips" the initial elements of a sequence that meet the criteria specified by the **predicate** and returns a new sequence containing the first element that doesn't meet the criteria as well as any elements that follow. 19 | 20 | Again, the **predicate** is provided as a delegate method that takes a single element of type `T` and returns a `bool` indicating whether or not the passed-in element should be "skipped". 21 | 22 | ```csharp 23 | List ints = new List { 1, 2, 4, 8, 4, 2, 1 }; 24 | // Will contain { 4, 8, 4, 2, 1 } 25 | IEnumerable result = ints.SkipWhile(theInt => theInt != 4); 26 | ``` 27 | 28 | # Exercise 29 | In this exercise, make the `GetStartThroughEnd()` method return all the words from the provided sequence that occur between the words "start" (inclusive) and "end" (non-inclusive). 30 | 31 | @[TakeWhile and SkipWhile Exercise]({"stubs": ["MultipleValue1/SkipTakeWhile1.cs"], "command": "MultipleValue1.UnitTest.Exercise2", "project": "exercises"}) 32 | -------------------------------------------------------------------------------- /markdowns/05_MethodsExtractValues/02_skip_while_take_while.template.md: -------------------------------------------------------------------------------- 1 | # Methods - Extract multiple elements 2 | 3 | In the previous lesson, we learned about `Take()` and `Skip()`, both of which accept an integer parameter. Each of these methods also have a variant that utilizes a delegate method to determine which elements will be taken or skipped. 4 | 5 | # [TakeWhile(<predicate>)](https://msdn.microsoft.com/en-us/library/bb534804%28v=vs.110%29.aspx) method 6 | `TakeWhile()` behaves similarly to the `Take()` method except that instead of taking the first `n` elements of a sequence, it "takes" all of the initial elements of a sequence that meet the criteria specified by the **predicate**, and stops on the first element that doesn't meet the criteria. It then returns a new sequence containing all the "taken" elements. 7 | 8 | The **predicate** is passed into `TakeWhile()` as a delegate method that takes a single parameter of type `T` (where `T` is the data type of the elements in the `IEnumerable` sequence) and returns a `bool` indicating whether or not the passed-in element should be "taken". 9 | 10 | ```csharp 11 | //// EMBED: LinqCourseEmbeddedCode/Methods2.cs, TakeWhile() 12 | ``` 13 | 14 | # [SkipWhile(<predicate>)](https://msdn.microsoft.com/en-us/library/bb549075%28v=vs.110%29.aspx) method 15 | Just as `Skip()` is the spiritual opposite of `Take()`, `SkipWhile()` is the opposite of `TakeWhile()`. `SkipWhile()` "skips" the initial elements of a sequence that meet the criteria specified by the **predicate** and returns a new sequence containing the first element that doesn't meet the criteria as well as any elements that follow. 16 | 17 | Again, the **predicate** is provided as a delegate method that takes a single element of type `T` and returns a `bool` indicating whether or not the passed-in element should be "skipped". 18 | 19 | ```csharp 20 | //// EMBED: LinqCourseEmbeddedCode/Methods2.cs, SkipWhile() 21 | ``` 22 | 23 | # Exercise 24 | In this exercise, make the `GetStartThroughEnd()` method return all the words from the provided sequence that occur between the words "start" (inclusive) and "end" (non-inclusive). 25 | 26 | @[TakeWhile and SkipWhile Exercise]({"stubs": ["MultipleValue1/SkipTakeWhile1.cs"], "command": "MultipleValue1.UnitTest.Exercise2", "project": "exercises"}) 27 | -------------------------------------------------------------------------------- /markdowns/05_MethodsExtractValues/03_distinct_intersection_where.md: -------------------------------------------------------------------------------- 1 | [//]: # (GENERATED FILE -- DO NOT EDIT) 2 | # Methods - Extract multiple elements 3 | 4 | `Take()` and `Skip()` return consecutive elements at the beginning and end of a sequence, but there are also ways to extract specific elements scattered throughout a given sequence. 5 | 6 | # [Distinct()](https://msdn.microsoft.com/en-us/library/bb348436%28v=vs.110%29.aspx) method 7 | The `Distinct()` method works the same way as the `DISTINCT` directive in SQL. It returns a new sequence containing all the elements from the target sequence that are distinct from each other, as determined by the [default equality comparer](https://msdn.microsoft.com/en-us/library/ms224763%28v=vs.110%29.aspx) for the data type of the sequence. 8 | 9 | For example: 10 | 11 | ```csharp 12 | List ints = new List { 1, 2, 4, 8, 4, 2, 1 }; 13 | // Will contain { 1, 2, 4, 8 } 14 | IEnumerable result = ints.Distinct(); 15 | ``` 16 | 17 | # [Intersect()](https://msdn.microsoft.com/en-us/library/bb460136%28v=vs.110%29.aspx) method 18 | `Intersect()` returns a new sequence containing all the elements that are common to both the target sequence and a second sequence provided as a parameter to the method. Both sequences must provide the same data type, and commonality is determined by the default equality comparer for that data type. 19 | 20 | ```csharp 21 | List ints = new List { 1, 2, 4, 8, 4, 2, 1 }; 22 | List filter = new List { 1, 1, 2, 3, 5, 8 }; 23 | // Will contain { 1, 2, 8 } 24 | IEnumerable result = ints.Intersect(filter); 25 | ``` 26 | 27 | # [Where(<predicate>)](https://msdn.microsoft.com/en-us/library/bb534803%28v=vs.110%29.aspx) method 28 | `Where()` returns a new sequence containing all the elements from the target sequence that meet a specified criteria. 29 | 30 | > **NOTE:** LINQ is showing its SQL roots here. The `Where()` method is named based on SQL syntax, but acts like the `filter()` function in Java, JavaScript, Python, etc. 31 | 32 | The criteria is passed into `Where()` as a **predicate** delegate method that takes a single parameter of type `T` (where `T` is the data type of the elements in the `IEnumerable` sequence) and returns a `bool` indicating whether or not the passed-in element should be included in the returned sequence. 33 | 34 | ```csharp 35 | List ints = new List { 1, 2, 4, 8, 4, 2, 1 }; 36 | // Will contain { 2, 4, 4, 2 } 37 | IEnumerable result = ints.Where(theInt => theInt == 2 || theInt == 4); 38 | ``` 39 | 40 | # Exercise 41 | In this exercise, make the `GetDistinctShortWords()` method return the words from the provided sequence that have fewer than four letters in them _and_ are distinct. 42 | 43 | @[Distinct, Intersect, and Where Exercise]({"stubs": ["MultipleValue1/DistinctIntersectWhere1.cs"], "command": "MultipleValue1.UnitTest.Exercise3", "project": "exercises"}) 44 | -------------------------------------------------------------------------------- /markdowns/05_MethodsExtractValues/03_distinct_intersection_where.template.md: -------------------------------------------------------------------------------- 1 | # Methods - Extract multiple elements 2 | 3 | `Take()` and `Skip()` return consecutive elements at the beginning and end of a sequence, but there are also ways to extract specific elements scattered throughout a given sequence. 4 | 5 | # [Distinct()](https://msdn.microsoft.com/en-us/library/bb348436%28v=vs.110%29.aspx) method 6 | The `Distinct()` method works the same way as the `DISTINCT` directive in SQL. It returns a new sequence containing all the elements from the target sequence that are distinct from each other, as determined by the [default equality comparer](https://msdn.microsoft.com/en-us/library/ms224763%28v=vs.110%29.aspx) for the data type of the sequence. 7 | 8 | For example: 9 | 10 | ```csharp 11 | //// EMBED: LinqCourseEmbeddedCode/Methods2.cs, Distinct() 12 | ``` 13 | 14 | # [Intersect()](https://msdn.microsoft.com/en-us/library/bb460136%28v=vs.110%29.aspx) method 15 | `Intersect()` returns a new sequence containing all the elements that are common to both the target sequence and a second sequence provided as a parameter to the method. Both sequences must provide the same data type, and commonality is determined by the default equality comparer for that data type. 16 | 17 | ```csharp 18 | //// EMBED: LinqCourseEmbeddedCode/Methods2.cs, Intersect() 19 | ``` 20 | 21 | # [Where(<predicate>)](https://msdn.microsoft.com/en-us/library/bb534803%28v=vs.110%29.aspx) method 22 | `Where()` returns a new sequence containing all the elements from the target sequence that meet a specified criteria. 23 | 24 | > **NOTE:** LINQ is showing its SQL roots here. The `Where()` method is named based on SQL syntax, but acts like the `filter()` function in Java, JavaScript, Python, etc. 25 | 26 | The criteria is passed into `Where()` as a **predicate** delegate method that takes a single parameter of type `T` (where `T` is the data type of the elements in the `IEnumerable` sequence) and returns a `bool` indicating whether or not the passed-in element should be included in the returned sequence. 27 | 28 | ```csharp 29 | //// EMBED: LinqCourseEmbeddedCode/Methods2.cs, Where() 30 | ``` 31 | 32 | # Exercise 33 | In this exercise, make the `GetDistinctShortWords()` method return the words from the provided sequence that have fewer than four letters in them _and_ are distinct. 34 | 35 | @[Distinct, Intersect, and Where Exercise]({"stubs": ["MultipleValue1/DistinctIntersectWhere1.cs"], "command": "MultipleValue1.UnitTest.Exercise3", "project": "exercises"}) 36 | -------------------------------------------------------------------------------- /markdowns/06_MethodsOrderElements/01_reverse_orderby.md: -------------------------------------------------------------------------------- 1 | [//]: # (GENERATED FILE -- DO NOT EDIT) 2 | # Methods - Changing element order 3 | 4 | These LINQ methods reorder the elements in an `IEnumerable` sequence. Each method in this chapter provides a different way of specifying the desired element order. 5 | 6 | > **NOTE:** Same comment as in the previous chapter. If I state that a method "returns a sequence", this is not technically true. The methods in this chapter return an `IEnumerable`, which is a generator (or an iterator) that can provide a sequence on demand. 7 | 8 | # [Reverse()](https://msdn.microsoft.com/en-us/library/bb358497%28v=vs.110%29.aspx) method 9 | The `Reverse()` method returns a new sequence that contains all the elements from the source sequence in the opposite order. 10 | 11 | ```csharp 12 | IEnumerable strings = new List { "first", "then", "and then", "finally" }; 13 | // Will contain { "finally", "and then", "then", "first" } 14 | IEnumerable result = strings.Reverse(); 15 | ``` 16 | 17 | > **NOTE:** The `Reverse()` LINQ method (an extension method to `IEnumerable`) behaves differently from the `Reverse()` method on `List`. This unfortunate situation can cause confusion. More on this in the **Advanced Topics** course. 18 | 19 | # [OrderBy(<keySelector>)](https://msdn.microsoft.com/en-us/library/bb534966%28v=vs.110%29.aspx) method 20 | `OrderBy()` sorts the elements in the source sequence based on a **key** value. The key for an element is calculated by a **keySelector** delegate method passed into the `OrderBy()` call. The examples below demonstrate how this works. 21 | 22 | ```csharp 23 | List strings = new List { "first", "then", "and then", "finally" }; 24 | // Sort the strings by their length 25 | // Will contain { "then", "first", "finally", "and then" } 26 | IEnumerable result = strings.OrderBy(str => str.Length); 27 | 28 | // Sort the strings by the 3rd character 29 | // Will contain { "and then", "then", "finally", "first" } 30 | IEnumerable result = strings.OrderBy(str => str[2]); 31 | 32 | // Sort the strings by their reversed characters 33 | // Will contain { "then", "and then", "first", "finally" } 34 | IEnumerable result = strings.OrderBy(str => new string(str.Reverse().ToArray())); 35 | ``` 36 | 37 | > **NOTE:** The **key** values are sorted based on the output of the [default comparer](https://msdn.microsoft.com/en-us/library/azhsac5f%28v=vs.110%29.aspx) for the data type of the keys. 38 | 39 | > **NOTE 2:** There is also an `OrderByDescending()` version of this method that sorts _in reverse order_ by the specified **key** value. 40 | 41 | ## There is no Sort() 42 | 43 | If you want to sort the elements within a sequence, then you will need to pass in an _identity_ **keySelector** method that indicates that each element in the sequence is, itself, a **key**. Here is what that looks like: 44 | 45 | ```csharp 46 | List strings = new List { "first", "then", "and then", "finally" }; 47 | // Sort the strings in alphabetical order 48 | // Will contain { "and then", "finally", "first", "then" } 49 | IEnumerable result = strings.OrderBy(str => str); 50 | ``` 51 | 52 | # OrderBy() exercise 53 | In the following exercise, try to sort all the input names by `Last`, in descending order. 54 | 55 | @[OrderBy Exercise]({"stubs": ["ChangeOrder1/OrderBy1.cs"], "command": "ChangeOrder1.UnitTest.Exercise1", "project": "exercises"}) 56 | -------------------------------------------------------------------------------- /markdowns/06_MethodsOrderElements/01_reverse_orderby.template.md: -------------------------------------------------------------------------------- 1 | # Methods - Changing element order 2 | 3 | These LINQ methods reorder the elements in an `IEnumerable` sequence. Each method in this chapter provides a different way of specifying the desired element order. 4 | 5 | > **NOTE:** Same comment as in the previous chapter. If I state that a method "returns a sequence", this is not technically true. The methods in this chapter return an `IEnumerable`, which is a generator (or an iterator) that can provide a sequence on demand. 6 | 7 | # [Reverse()](https://msdn.microsoft.com/en-us/library/bb358497%28v=vs.110%29.aspx) method 8 | The `Reverse()` method returns a new sequence that contains all the elements from the source sequence in the opposite order. 9 | 10 | ```csharp 11 | //// EMBED: LinqCourseEmbeddedCode/Methods3.cs, Reverse() 12 | ``` 13 | 14 | > **NOTE:** The `Reverse()` LINQ method (an extension method to `IEnumerable`) behaves differently from the `Reverse()` method on `List`. This unfortunate situation can cause confusion. More on this in the **Advanced Topics** course. 15 | 16 | # [OrderBy(<keySelector>)](https://msdn.microsoft.com/en-us/library/bb534966%28v=vs.110%29.aspx) method 17 | `OrderBy()` sorts the elements in the source sequence based on a **key** value. The key for an element is calculated by a **keySelector** delegate method passed into the `OrderBy()` call. The examples below demonstrate how this works. 18 | 19 | ```csharp 20 | //// EMBED: LinqCourseEmbeddedCode/Methods3.cs, OrderBy() 1 21 | 22 | //// EMBED: LinqCourseEmbeddedCode/Methods3.cs, OrderBy() 2 23 | 24 | //// EMBED: LinqCourseEmbeddedCode/Methods3.cs, OrderBy() 3 25 | ``` 26 | 27 | > **NOTE:** The **key** values are sorted based on the output of the [default comparer](https://msdn.microsoft.com/en-us/library/azhsac5f%28v=vs.110%29.aspx) for the data type of the keys. 28 | 29 | > **NOTE 2:** There is also an `OrderByDescending()` version of this method that sorts _in reverse order_ by the specified **key** value. 30 | 31 | ## There is no Sort() 32 | 33 | If you want to sort the elements within a sequence, then you will need to pass in an _identity_ **keySelector** method that indicates that each element in the sequence is, itself, a **key**. Here is what that looks like: 34 | 35 | ```csharp 36 | //// EMBED: LinqCourseEmbeddedCode/Methods3.cs, OrderBy() identity 37 | ``` 38 | 39 | # OrderBy() exercise 40 | In the following exercise, try to sort all the input names by `Last`, in descending order. 41 | 42 | @[OrderBy Exercise]({"stubs": ["ChangeOrder1/OrderBy1.cs"], "command": "ChangeOrder1.UnitTest.Exercise1", "project": "exercises"}) 43 | -------------------------------------------------------------------------------- /markdowns/06_MethodsOrderElements/02_thenby.md: -------------------------------------------------------------------------------- 1 | [//]: # (GENERATED FILE -- DO NOT EDIT) 2 | # [ThenBy(<keySelector>)](https://msdn.microsoft.com/en-us/library/bb534743%28v=vs.110%29.aspx) method 3 | `ThenBy()` specifies a secondary sort **key** that is used to further sort data that has already been sorted with a call to `OrderBy()`. 4 | 5 | ## IOrderedEnumerable<T> 6 | `ThenBy()` is an interesting method. It is not an extension to `IEnumerable`. Instead, it is a method of the `IOrderedEnumerable` type, which is returned from `OrderBy()`, `OrderByDescending()`, `ThenBy()`, and `ThenByDescending()`. 7 | 8 | Since `IOrderedEnumerable` implements the `IEnumerable` interface, it can be thought of as an `IEnumerable` with attached metadata that describes the order operations that have previously been performed on the sequence. 9 | 10 | `ThenBy()` can be called any number of times, providing a new **key** on each subsequent call. Here is an example of `ThenBy()` usage: 11 | 12 | ```csharp 13 | List strings = new List { "first", "then", "and then", "finally" }; 14 | // Order by the last character, then by the first character 15 | // Will contain { "and then", "then", "first", "finally" } 16 | IEnumerable result = strings.OrderBy(str => str.Last()).ThenBy(str => str.First()); 17 | ``` 18 | 19 | ?[Which of the following use correct syntax?] 20 | - [x] names = names.OrderBy(n => n.Last).ThenBy(n => n.First) 21 | - [ ] planets = planets.OrderBy(p => p.Type).Reverse().ThenBy(p => p.Size) 22 | - [x] houses = houses.OrderBy(h => h.BedRooms).ThenBy(h => h.Baths).ThenBy(h => h.Size) 23 | - [ ] drinks = drinks.OrderBy(d => d.Calories).ThenBy(d.CaffeineContent).ThenBy(d.Price) 24 | - [ ] dogs = dogs.ThenBy(d => d.Color) 25 | 26 | # ThenBy() exercise 27 | In the following exercise, try to order all the input names by `Last`. If any names have the same value for `Last`, then they should be ordered by `First`. If any have matching `Last` and `First`, then they should be ordered by `Middle`. 28 | 29 | @[ThenBy Exercise]({"stubs": ["ChangeOrder1/ThenBy1.cs"], "command": "ChangeOrder1.UnitTest.Exercise2", "project": "exercises"}) 30 | -------------------------------------------------------------------------------- /markdowns/06_MethodsOrderElements/02_thenby.template.md: -------------------------------------------------------------------------------- 1 | # [ThenBy(<keySelector>)](https://msdn.microsoft.com/en-us/library/bb534743%28v=vs.110%29.aspx) method 2 | `ThenBy()` specifies a secondary sort **key** that is used to further sort data that has already been sorted with a call to `OrderBy()`. 3 | 4 | ## IOrderedEnumerable<T> 5 | `ThenBy()` is an interesting method. It is not an extension to `IEnumerable`. Instead, it is a method of the `IOrderedEnumerable` type, which is returned from `OrderBy()`, `OrderByDescending()`, `ThenBy()`, and `ThenByDescending()`. 6 | 7 | Since `IOrderedEnumerable` implements the `IEnumerable` interface, it can be thought of as an `IEnumerable` with attached metadata that describes the order operations that have previously been performed on the sequence. 8 | 9 | `ThenBy()` can be called any number of times, providing a new **key** on each subsequent call. Here is an example of `ThenBy()` usage: 10 | 11 | ```csharp 12 | //// EMBED: LinqCourseEmbeddedCode/Methods3.cs, ThenBy() 13 | ``` 14 | 15 | ?[Which of the following use correct syntax?] 16 | - [x] names = names.OrderBy(n => n.Last).ThenBy(n => n.First) 17 | - [ ] planets = planets.OrderBy(p => p.Type).Reverse().ThenBy(p => p.Size) 18 | - [x] houses = houses.OrderBy(h => h.BedRooms).ThenBy(h => h.Baths).ThenBy(h => h.Size) 19 | - [ ] drinks = drinks.OrderBy(d => d.Calories).ThenBy(d.CaffeineContent).ThenBy(d.Price) 20 | - [ ] dogs = dogs.ThenBy(d => d.Color) 21 | 22 | # ThenBy() exercise 23 | In the following exercise, try to order all the input names by `Last`. If any names have the same value for `Last`, then they should be ordered by `First`. If any have matching `Last` and `First`, then they should be ordered by `Middle`. 24 | 25 | @[ThenBy Exercise]({"stubs": ["ChangeOrder1/ThenBy1.cs"], "command": "ChangeOrder1.UnitTest.Exercise2", "project": "exercises"}) 26 | -------------------------------------------------------------------------------- /markdowns/07_MethodsCalculateSingleValue/01_count.md: -------------------------------------------------------------------------------- 1 | [//]: # (GENERATED FILE -- DO NOT EDIT) 2 | # Methods - Calculating a single value 3 | 4 | The LINQ methods in this chapter examine the elements of an `IEnumerable` sequence and return a result based on the examined values. For most of the methods we will discuss, this returned result will be either a `bool` or an `int`. 5 | 6 | # [Count()](https://msdn.microsoft.com/en-us/library/bb338038%28v=vs.110%29.aspx) method 7 | In its simplest form (without any parameters), the `Count()` method returns an `int` indicating the number of elements in the source sequence. 8 | 9 | ```csharp 10 | IEnumerable strings = new List { "first", "then", "and then", "finally" }; 11 | // Will return 4 12 | int result = strings.Count(); 13 | ``` 14 | 15 | > **NOTE:** The `Count()` LINQ method (an extension method to `IEnumerable`) is slightly different from the `Count` property on `List`. This unfortunate situation can cause some confusion. More on this in the **Advanced Topics** course. 16 | 17 | > **NOTE:** There is also a `LongCount()` method that returns a `long`, for use with sequences that have a large number of elements. 18 | 19 | # [Count(<predicate>)](https://msdn.microsoft.com/en-us/library/bb535181%28v=vs.110%29.aspx) method 20 | There is another form of the `Count()` method that takes a **predicate** delegate parameter. The provided delegate should take a parameter of type `T` and return a `bool` indicating whether or not the provided parameter meets the criteria. 21 | 22 | This form of `Count()` will return an `int` indicating the number of elements in the source sequence that meet the criteria. This produces the same result as `.Where().Count()`. 23 | 24 | ```csharp 25 | IEnumerable strings = new List { "first", "then", "and then", "finally" }; 26 | // Will return 2 27 | int result = strings.Count(str => str.Contains("then")); 28 | ``` 29 | 30 | # Count() exercise 31 | In the following exercise, count the number of strings in the provided sequence that begin with the provided string. 32 | 33 | > **HINT:** Use the [`String.StartsWith()`](https://msdn.microsoft.com/en-us/library/baketfxw%28v=vs.110%29.aspx) method. 34 | 35 | @[Count Exercise]({"stubs": ["SingleCalculatedValue1/Count1.cs"], "command": "SingleCalculatedValue1.UnitTest.Exercise1", "project": "exercises"}) 36 | -------------------------------------------------------------------------------- /markdowns/07_MethodsCalculateSingleValue/01_count.template.md: -------------------------------------------------------------------------------- 1 | # Methods - Calculating a single value 2 | 3 | The LINQ methods in this chapter examine the elements of an `IEnumerable` sequence and return a result based on the examined values. For most of the methods we will discuss, this returned result will be either a `bool` or an `int`. 4 | 5 | # [Count()](https://msdn.microsoft.com/en-us/library/bb338038%28v=vs.110%29.aspx) method 6 | In its simplest form (without any parameters), the `Count()` method returns an `int` indicating the number of elements in the source sequence. 7 | 8 | ```csharp 9 | //// EMBED: LinqCourseEmbeddedCode/Methods4.cs, Count() 10 | ``` 11 | 12 | > **NOTE:** The `Count()` LINQ method (an extension method to `IEnumerable`) is slightly different from the `Count` property on `List`. This unfortunate situation can cause some confusion. More on this in the **Advanced Topics** course. 13 | 14 | > **NOTE:** There is also a `LongCount()` method that returns a `long`, for use with sequences that have a large number of elements. 15 | 16 | # [Count(<predicate>)](https://msdn.microsoft.com/en-us/library/bb535181%28v=vs.110%29.aspx) method 17 | There is another form of the `Count()` method that takes a **predicate** delegate parameter. The provided delegate should take a parameter of type `T` and return a `bool` indicating whether or not the provided parameter meets the criteria. 18 | 19 | This form of `Count()` will return an `int` indicating the number of elements in the source sequence that meet the criteria. This produces the same result as `.Where().Count()`. 20 | 21 | ```csharp 22 | //// EMBED: LinqCourseEmbeddedCode/Methods4.cs, Count() condition 23 | ``` 24 | 25 | # Count() exercise 26 | In the following exercise, count the number of strings in the provided sequence that begin with the provided string. 27 | 28 | > **HINT:** Use the [`String.StartsWith()`](https://msdn.microsoft.com/en-us/library/baketfxw%28v=vs.110%29.aspx) method. 29 | 30 | @[Count Exercise]({"stubs": ["SingleCalculatedValue1/Count1.cs"], "command": "SingleCalculatedValue1.UnitTest.Exercise1", "project": "exercises"}) 31 | -------------------------------------------------------------------------------- /markdowns/07_MethodsCalculateSingleValue/02_sum.md: -------------------------------------------------------------------------------- 1 | [//]: # (GENERATED FILE -- DO NOT EDIT) 2 | # [Sum()](https://msdn.microsoft.com/en-us/library/bb338442%28v=vs.110%29.aspx) method 3 | Without a parameter, the `Sum()` method can only be called on a sequence containing numerical elements. It returns a single value indicating the sum of all elements in the sequence. The type of the value returned matches the data type of the elements in the sequence. 4 | 5 | ```csharp 6 | IEnumerable ints = new List { 2, 2, 4, 6 }; 7 | // Will return 14 8 | int result = ints.Sum(); 9 | ``` 10 | 11 | # [Sum(<selector>)](https://msdn.microsoft.com/en-us/library/bb535184%28v=vs.110%29.aspx) method 12 | The `Sum()` method can also be called with a **selector** delegate parameter. The provided delegate should take a parameter of type `T` and return a numerical value. The result of the `Sum()` call will be the summation of all of these numerical values, as calculated for each element in the sequence. The type of the value returned from `Sum()` matches the data type of the of the value returned from the **selector**. 13 | 14 | ```csharp 15 | IEnumerable ints = new List { 2, 2, 4, 6 }; 16 | // Will return 60 17 | int result = ints.Sum(val => val * val); 18 | ``` 19 | 20 | # Sum() quiz 21 | ```csharp 22 | IEnumerable strings = new List { "a", "ab", "abc" }; 23 | var result = strings.Sum(str => 2.3F); 24 | ``` 25 | ?[What value and data type would the Sum() method return in the code snippet above?] 26 | - [ ] 3 (int) 27 | - [ ] 6 (int) 28 | - [ ] 6.9 (double) 29 | - [x] 6.9 (float) 30 | 31 | ```csharp 32 | IEnumerable strings = new List { "a", "ab", "abc" }; 33 | var result = strings.Sum(str => str.Length); 34 | ``` 35 | ?[What value and data type would the Sum() method return in the code snippet above?] 36 | - [ ] 3 (int) 37 | - [x] 6 (int) 38 | - [ ] 6.9 (double) 39 | - [ ] 6 (float) 40 | -------------------------------------------------------------------------------- /markdowns/07_MethodsCalculateSingleValue/02_sum.template.md: -------------------------------------------------------------------------------- 1 | # [Sum()](https://msdn.microsoft.com/en-us/library/bb338442%28v=vs.110%29.aspx) method 2 | Without a parameter, the `Sum()` method can only be called on a sequence containing numerical elements. It returns a single value indicating the sum of all elements in the sequence. The type of the value returned matches the data type of the elements in the sequence. 3 | 4 | ```csharp 5 | //// EMBED: LinqCourseEmbeddedCode/Methods4.cs, Sum() 6 | ``` 7 | 8 | # [Sum(<selector>)](https://msdn.microsoft.com/en-us/library/bb535184%28v=vs.110%29.aspx) method 9 | The `Sum()` method can also be called with a **selector** delegate parameter. The provided delegate should take a parameter of type `T` and return a numerical value. The result of the `Sum()` call will be the summation of all of these numerical values, as calculated for each element in the sequence. The type of the value returned from `Sum()` matches the data type of the of the value returned from the **selector**. 10 | 11 | ```csharp 12 | //// EMBED: LinqCourseEmbeddedCode/Methods4.cs, Sum() selector 13 | ``` 14 | 15 | # Sum() quiz 16 | ```csharp 17 | //// EMBED: LinqCourseEmbeddedCode/Methods4.cs, Sum() question 1 18 | ``` 19 | ?[What value and data type would the Sum() method return in the code snippet above?] 20 | - [ ] 3 (int) 21 | - [ ] 6 (int) 22 | - [ ] 6.9 (double) 23 | - [x] 6.9 (float) 24 | 25 | ```csharp 26 | //// EMBED: LinqCourseEmbeddedCode/Methods4.cs, Sum() question 2 27 | ``` 28 | ?[What value and data type would the Sum() method return in the code snippet above?] 29 | - [ ] 3 (int) 30 | - [x] 6 (int) 31 | - [ ] 6.9 (double) 32 | - [ ] 6 (float) 33 | -------------------------------------------------------------------------------- /markdowns/07_MethodsCalculateSingleValue/03_min_max.md: -------------------------------------------------------------------------------- 1 | [//]: # (GENERATED FILE -- DO NOT EDIT) 2 | # [Min()](https://msdn.microsoft.com/en-us/library/bb339189%28v=vs.110%29.aspx) and [Max()](https://msdn.microsoft.com/en-us/library/bb292667%28v=vs.110%29.aspx) methods 3 | Very simply, the `Min()` method returns the minimum value from the source sequence and the `Max()` method returns the maximum value. As with the `Sum()` method, they can only be called on sequences containing numerical values. 4 | 5 | ```csharp 6 | IEnumerable ints = new List { 2, 2, 4, 6, 3, 6, 5 }; 7 | // Will return 6 8 | int result = ints.Max(); 9 | ``` 10 | 11 | # [Min(<selector>)](https://msdn.microsoft.com/en-us/library/bb549416%28v=vs.110%29.aspx) and [Max(<selector>)](https://msdn.microsoft.com/en-us/library/bb535031%28v=vs.110%29.aspx) methods 12 | Similar to the `Sum()` method, `Min()` and `Max()` can also be called with a **selector** delegate parameter. The provided delegate should take a parameter of type `T` and return a numerical value. The result of the `Min()` or `Max()` method call will be the minimum or maximum of all of these numerical values, as calculated for each element in the sequence. The type of the value returned from `Min()` or `Max()` matches the data type of the of the value returned from the **selector**. 13 | 14 | ```csharp 15 | IEnumerable strings = new List { "1.2", "1.3", "1.5", "0.6" }; 16 | // Will return 0.6 17 | float result = strings.Min(str => float.Parse(str)); 18 | ``` 19 | 20 | # Min() / Max() exercise 21 | In the following exercise, write a method that will return the length of the shortest string in the provided sequence as an integer value. 22 | 23 | @[Min / Max Exercise]({"stubs": ["SingleCalculatedValue1/MinMax1.cs"], "command": "SingleCalculatedValue1.UnitTest.Exercise2", "project": "exercises"}) 24 | -------------------------------------------------------------------------------- /markdowns/07_MethodsCalculateSingleValue/03_min_max.template.md: -------------------------------------------------------------------------------- 1 | # [Min()](https://msdn.microsoft.com/en-us/library/bb339189%28v=vs.110%29.aspx) and [Max()](https://msdn.microsoft.com/en-us/library/bb292667%28v=vs.110%29.aspx) methods 2 | Very simply, the `Min()` method returns the minimum value from the source sequence and the `Max()` method returns the maximum value. As with the `Sum()` method, they can only be called on sequences containing numerical values. 3 | 4 | ```csharp 5 | //// EMBED: LinqCourseEmbeddedCode/Methods4.cs, Max() 6 | ``` 7 | 8 | # [Min(<selector>)](https://msdn.microsoft.com/en-us/library/bb549416%28v=vs.110%29.aspx) and [Max(<selector>)](https://msdn.microsoft.com/en-us/library/bb535031%28v=vs.110%29.aspx) methods 9 | Similar to the `Sum()` method, `Min()` and `Max()` can also be called with a **selector** delegate parameter. The provided delegate should take a parameter of type `T` and return a numerical value. The result of the `Min()` or `Max()` method call will be the minimum or maximum of all of these numerical values, as calculated for each element in the sequence. The type of the value returned from `Min()` or `Max()` matches the data type of the of the value returned from the **selector**. 10 | 11 | ```csharp 12 | //// EMBED: LinqCourseEmbeddedCode/Methods4.cs, Min() selector 13 | ``` 14 | 15 | # Min() / Max() exercise 16 | In the following exercise, write a method that will return the length of the shortest string in the provided sequence as an integer value. 17 | 18 | @[Min / Max Exercise]({"stubs": ["SingleCalculatedValue1/MinMax1.cs"], "command": "SingleCalculatedValue1.UnitTest.Exercise2", "project": "exercises"}) 19 | -------------------------------------------------------------------------------- /markdowns/07_MethodsCalculateSingleValue/04_any_all.md: -------------------------------------------------------------------------------- 1 | [//]: # (GENERATED FILE -- DO NOT EDIT) 2 | # [Any(<predicate>)](https://msdn.microsoft.com/en-us/library/bb534972%28v=vs.110%29.aspx) method 3 | Returns `true` if _at least one of the elements_ in the source sequence matches the provided **predicate**. Otherwise it returns `false`. 4 | 5 | ```csharp 6 | IEnumerable doubles = new List { 1.2, 1.7, 2.5, 2.4 }; 7 | // Will return false 8 | bool result = doubles.Any(val => val < 1); 9 | ``` 10 | 11 | > **NOTE:** `Any()` can also be called [without a predicate](https://msdn.microsoft.com/en-us/library/bb337697%28v=vs.110%29.aspx), in which case it will return `true` if there is at least one element in the source sequence. 12 | 13 | # [All(<predicate>)](https://msdn.microsoft.com/en-us/library/bb548541%28v=vs.110%29.aspx) method 14 | Returns `true` if _every element_ in the source sequence matches the provided **predicate**. Otherwise it returns `false`. 15 | 16 | ```csharp 17 | IEnumerable strings = new List { "one", "three", "five" }; 18 | // Will return true 19 | bool result = strings.All(str => str.Contains("e")); 20 | ``` 21 | 22 | # Any() / All() quiz 23 | ```csharp 24 | string result = "none"; 25 | IEnumerable strings = new List { "four", "one", "two", "three", "five" }; 26 | if (strings.Take(3).Any(s => s.StartsWith("a"))) 27 | { 28 | if (strings.Skip(1).Take(2).All(s => s.Length == 3)) 29 | { 30 | result = "red"; 31 | } 32 | else 33 | { 34 | result = "orange"; 35 | } 36 | } 37 | else 38 | { 39 | if (strings.All(s => s.Length > 2)) 40 | { 41 | if (strings.OrderBy(s => s).Take(3).Any(s => s == "one")) 42 | { 43 | result = "yellow"; 44 | } 45 | else 46 | { 47 | result = "green"; 48 | } 49 | } 50 | else 51 | { 52 | result = "blue"; 53 | } 54 | } 55 | ``` 56 | 57 | ?[What would be the value of the "result" variable in the code snippet above?] 58 | - [ ] none 59 | - [ ] red 60 | - [ ] orange 61 | - [x] yellow 62 | - [ ] green 63 | - [ ] blue 64 | -------------------------------------------------------------------------------- /markdowns/07_MethodsCalculateSingleValue/04_any_all.template.md: -------------------------------------------------------------------------------- 1 | # [Any(<predicate>)](https://msdn.microsoft.com/en-us/library/bb534972%28v=vs.110%29.aspx) method 2 | Returns `true` if _at least one of the elements_ in the source sequence matches the provided **predicate**. Otherwise it returns `false`. 3 | 4 | ```csharp 5 | //// EMBED: LinqCourseEmbeddedCode/Methods4.cs, Any() 6 | ``` 7 | 8 | > **NOTE:** `Any()` can also be called [without a predicate](https://msdn.microsoft.com/en-us/library/bb337697%28v=vs.110%29.aspx), in which case it will return `true` if there is at least one element in the source sequence. 9 | 10 | # [All(<predicate>)](https://msdn.microsoft.com/en-us/library/bb548541%28v=vs.110%29.aspx) method 11 | Returns `true` if _every element_ in the source sequence matches the provided **predicate**. Otherwise it returns `false`. 12 | 13 | ```csharp 14 | //// EMBED: LinqCourseEmbeddedCode/Methods4.cs, All() 15 | ``` 16 | 17 | # Any() / All() quiz 18 | ```csharp 19 | //// EMBED: LinqCourseEmbeddedCode/Methods4.cs, Any() All() question 20 | ``` 21 | 22 | ?[What would be the value of the "result" variable in the code snippet above?] 23 | - [ ] none 24 | - [ ] red 25 | - [ ] orange 26 | - [x] yellow 27 | - [ ] green 28 | - [ ] blue 29 | -------------------------------------------------------------------------------- /markdowns/07_MethodsCalculateSingleValue/05_sequenceequal.md: -------------------------------------------------------------------------------- 1 | [//]: # (GENERATED FILE -- DO NOT EDIT) 2 | # [SequenceEqual()](https://msdn.microsoft.com/en-us/library/bb348567%28v=vs.110%29.aspx) method 3 | The `SequenceEqual()` method takes a **second** `IEnumerable` sequence as a parameter, and performs a comparison, element-by-element, with the target (first) sequence. If the two sequences contain the same number of elements, and each element in the first sequence is equal to the corresponding element in the second sequence (using the [default equality comparer](https://msdn.microsoft.com/en-us/library/ms224763%28v=vs.110%29.aspx)) then `SequenceEqual()` returns `true`. Otherwise, `false` is returned. 4 | 5 | It is interesting to note that this can be used to compare *any* two sequences! So, for example, a list and an array can be compared using this method. It can be quite handy sometimes. The only stipulation is that the data type of the two sequences, ``, must be the same. 6 | 7 | ```csharp 8 | // returns true 9 | bool isEqual1 = new[] { 1, 2, 3 }.SequenceEqual(new List { 1, 2, 3 }); 10 | 11 | // returns false 12 | bool isEqual2 = new List { 1, 2, 3, 4 }.SequenceEqual(new[] { 1, 2, 3 }); 13 | 14 | // returns true 15 | bool isEqual3 = new List { 1, 2, 3, 4 }.Take(3).SequenceEqual(new[] { 1, 2, 3 }); 16 | 17 | // returns false 18 | bool isEqual4 = new[] { 2, 1, 2 }.SequenceEqual(new[] { 1, 1, 2 }); 19 | 20 | // returns true 21 | bool isEqual5 = new[] { 2, 1, 2 }.Skip(1).SequenceEqual(new[] { 1, 1, 2 }.Skip(1)); 22 | ``` 23 | 24 | > **NOTE:** There is also another form of `SequenceEqual()` that takes an `IEqualityComparer` comparer parameter to use instead of the default equality comparer. 25 | 26 | # SequenceEqual() quiz 27 | Which of the following would _both_ compile correctly _and_ return `true`? 28 | 29 | ?[Which statements would compile and return true?] 30 | - [ ] new[]{2}.SequenceEqual(2) 31 | - [x] new SortedSet<int>{1,2,4}.SequenceEqual(new[]{1,2,4}) 32 | - [ ] new[]{2,5,2}.SequenceEqual(new[]{2,5,2,2}) 33 | - [ ] new[]{1,1,1}.SequenceEqual(new[]{1,1}) 34 | - [ ] new[]{"1","2","3"}.SequenceEqual(new[]{1,2,3}) 35 | - [x] new List<string>{"a","b","abc"}.SequenceEqual(new[]{"a","b","abc"}) 36 | - [ ] new[]{1,2}.SequenceEqual(new[]{1.0,2.0}) 37 | -------------------------------------------------------------------------------- /markdowns/07_MethodsCalculateSingleValue/05_sequenceequal.template.md: -------------------------------------------------------------------------------- 1 | # [SequenceEqual()](https://msdn.microsoft.com/en-us/library/bb348567%28v=vs.110%29.aspx) method 2 | The `SequenceEqual()` method takes a **second** `IEnumerable` sequence as a parameter, and performs a comparison, element-by-element, with the target (first) sequence. If the two sequences contain the same number of elements, and each element in the first sequence is equal to the corresponding element in the second sequence (using the [default equality comparer](https://msdn.microsoft.com/en-us/library/ms224763%28v=vs.110%29.aspx)) then `SequenceEqual()` returns `true`. Otherwise, `false` is returned. 3 | 4 | It is interesting to note that this can be used to compare *any* two sequences! So, for example, a list and an array can be compared using this method. It can be quite handy sometimes. The only stipulation is that the data type of the two sequences, ``, must be the same. 5 | 6 | ```csharp 7 | //// EMBED: LinqCourseEmbeddedCode/Methods4.cs, SequenceEqual() 8 | ``` 9 | 10 | > **NOTE:** There is also another form of `SequenceEqual()` that takes an `IEqualityComparer` comparer parameter to use instead of the default equality comparer. 11 | 12 | # SequenceEqual() quiz 13 | Which of the following would _both_ compile correctly _and_ return `true`? 14 | 15 | ?[Which statements would compile and return true?] 16 | - [ ] new[]{2}.SequenceEqual(2) 17 | - [x] new SortedSet<int>{1,2,4}.SequenceEqual(new[]{1,2,4}) 18 | - [ ] new[]{2,5,2}.SequenceEqual(new[]{2,5,2,2}) 19 | - [ ] new[]{1,1,1}.SequenceEqual(new[]{1,1}) 20 | - [ ] new[]{"1","2","3"}.SequenceEqual(new[]{1,2,3}) 21 | - [x] new List<string>{"a","b","abc"}.SequenceEqual(new[]{"a","b","abc"}) 22 | - [ ] new[]{1,2}.SequenceEqual(new[]{1.0,2.0}) 23 | -------------------------------------------------------------------------------- /markdowns/07_MethodsCalculateSingleValue/06_aggregate.template.md: -------------------------------------------------------------------------------- 1 | # [Aggregate(<func>)](https://msdn.microsoft.com/en-us/library/bb548651%28v=vs.110%29.aspx) method 2 | The `Aggregate()` method applies a function to all the elements of the source sequence and calculates a cumulative result that takes into account the return value of each function call. 3 | 4 | This is a somewhat complicated concept, and is best shown with some examples. 5 | 6 | ```csharp 7 | //// EMBED: LinqCourseEmbeddedCode/Methods4.cs, Aggregate() -> Sum() 8 | ``` 9 | 10 | What's happening in this example? We have provided the lambda expression `(sum, val) => sum + val` to the `Aggregate()` method. This expression will be executed 3 (length of the list - 1) times: 11 | 12 | 1. It is passed 2 and 4 for the `sum` and `val` parameters, and returns the sum: 6. 13 | 2. It is passed 6 and 1 for `sum` and `val`, and returns 7. 14 | 3. It is passed 7 and 6 and returns 13. 15 | 16 | 17 | ```csharp 18 | //// EMBED: LinqCourseEmbeddedCode/Methods4.cs, Aggregate() -> concat 19 | ``` 20 | 21 | In this example, the expression `(concat, str) => $"{concat}&{str}"` is called 4 times: 22 | 23 | 1. It is passed "a" and "ab" for the `concat` and `str` parameters, and returns "a&ab". 24 | 2. It is passed "a&ab" and "abc" and returns "a&ab&abc". 25 | 3. "a&ab&abc" and "abcd" → "a&ab&abc&abcd" 26 | 4. "a&ab&abc&abcd" and "z" → "a&ab&abc&abcd&z" 27 | 28 | > **NOTE:** The return value of the `Aggregate()` call (and the provided **func**) must be the same data type as that of the elements in the source sequence. 29 | 30 | # [Aggregate(<seed>, <func>)](https://msdn.microsoft.com/en-us/library/bb549218%28v=vs.110%29.aspx) method 31 | Another form of `Aggregate()` takes a **seed**, which specifies the initial value supplied to the **func**. In addition, this form of `Aggregate()` can return a value of a different data type than that of the elements in the source sequence. In this case, the data type of the value returned from **func** must match the data type of **seed**. 32 | 33 | ```csharp 34 | //// EMBED: LinqCourseEmbeddedCode/Methods4.cs, Aggregate() -> Count() 35 | ``` 36 | 37 | In this example, the expression `(count, val) => count + 1` is called 4 times: 38 | 39 | 1. It is passed 0 and "a" for the `count` and `val` parameters, and returns 1. 40 | 2. It is passed 1 and "ab" and returns 2. 41 | 3. 2 and "abc" → 3 42 | 4. 3 and "abcd" → 4 43 | 44 | ```csharp 45 | //// EMBED: LinqCourseEmbeddedCode/Methods4.cs, Aggregate() -> Any() 46 | ``` 47 | In this example, the expression `(any, val) => any || (val.Length > 3)` is called 5 times: 48 | 49 | 1. It is passed `false` and "a" for the `any` and `val` parameters, and returns `false`. 50 | 2. It is passed `false` and "ab" and returns `false`. 51 | 3. `false` and "abc" → `false` 52 | 4. `false` and "abcd" → `true` 53 | 5. `true` and "z" → `true` 54 | 55 | # Aggregate() exercise 56 | Think you can handle it? Try to use `Aggregate()` to write a method that will return the total number of characters in all the words in the source sequence. 57 | 58 | @[Aggregate Exercise]({"stubs": ["SingleCalculatedValue1/Aggregate1.cs"], "command": "SingleCalculatedValue1.UnitTest.Exercise3", "project": "exercises"}) 59 | -------------------------------------------------------------------------------- /markdowns/08_MethodsCalculateSequence/01_cast.md: -------------------------------------------------------------------------------- 1 | [//]: # (GENERATED FILE -- DO NOT EDIT) 2 | # Methods - Calculate a new sequence 3 | 4 | These LINQ methods can be used to create a new `IEnumerable` result sequence based on the values in the source sequence. 5 | 6 | > **NOTE:** Same comment as before. If I state that a method "returns a sequence," this is not technically true. The methods in this chapter return an `IEnumerable`, which is a generator (or an iterator) that can provide a sequence on demand. 7 | 8 | # [Cast<U>()](https://msdn.microsoft.com/en-us/library/bb341406%28v=vs.110%29.aspx) method 9 | The `Cast()` method casts each element of a source `IEnumerable` sequence, individually, to a base or derived type `U` and returns a sequence containing all of the resultant elements. 10 | 11 | > **NOTE:** If the source type `T` can't be cast to the result type `U` then the cast will fail with an `InvalidCastException`. 12 | 13 | ```csharp 14 | IEnumerable values = new List { 2, 3, 4 }; 15 | // Will return { 2, 3, 4 } 16 | // The elements in the collection are the same, 17 | // but the collection type is different 18 | IEnumerable result = values.Cast(); 19 | ``` 20 | 21 | ```csharp 22 | IEnumerable strings = new List { "one", "two", "three" }; 23 | // Will throw InvalidCastException 24 | IEnumerable result = strings.Cast(); 25 | Console.WriteLine(result.First()); 26 | ``` 27 | 28 | > **NOTE:** Casting to a more-derived type is always a dubious activity, and typically indicates a failure in polymorphic design. `Cast` should more likely be used to cast to a less-derived, base type. 29 | -------------------------------------------------------------------------------- /markdowns/08_MethodsCalculateSequence/01_cast.template.md: -------------------------------------------------------------------------------- 1 | # Methods - Calculate a new sequence 2 | 3 | These LINQ methods can be used to create a new `IEnumerable` result sequence based on the values in the source sequence. 4 | 5 | > **NOTE:** Same comment as before. If I state that a method "returns a sequence," this is not technically true. The methods in this chapter return an `IEnumerable`, which is a generator (or an iterator) that can provide a sequence on demand. 6 | 7 | # [Cast<U>()](https://msdn.microsoft.com/en-us/library/bb341406%28v=vs.110%29.aspx) method 8 | The `Cast()` method casts each element of a source `IEnumerable` sequence, individually, to a base or derived type `U` and returns a sequence containing all of the resultant elements. 9 | 10 | > **NOTE:** If the source type `T` can't be cast to the result type `U` then the cast will fail with an `InvalidCastException`. 11 | 12 | ```csharp 13 | //// EMBED: LinqCourseEmbeddedCode/Methods5.cs, Cast() good 14 | ``` 15 | 16 | ```csharp 17 | //// EMBED: LinqCourseEmbeddedCode/Methods5.cs, Cast() bad 18 | ``` 19 | 20 | > **NOTE:** Casting to a more-derived type is always a dubious activity, and typically indicates a failure in polymorphic design. `Cast` should more likely be used to cast to a less-derived, base type. 21 | -------------------------------------------------------------------------------- /markdowns/08_MethodsCalculateSequence/02_select.md: -------------------------------------------------------------------------------- 1 | [//]: # (GENERATED FILE -- DO NOT EDIT) 2 | # [Select(<selector>)](https://msdn.microsoft.com/en-us/library/bb548891%28v=vs.110%29.aspx) method 3 | The `Select()` method invokes the provided **selector** delegate on each element of the source `IEnumerable` sequence, and returns a new result `IEnumerable` sequence containing the output of each invocation. 4 | 5 | Wow! That's a mouthful! Let's try it this way. `Select()` takes each source element, transforms it, and returns a sequence of the transformed values. Better? 6 | 7 | > **NOTE:** Here we see LINQ showing its SQL roots again. The `Select()` method is named based on SQL syntax, but acts like the `map()` function in Java, JavaScript, Python, etc. 8 | 9 | The **selector** method should take a single parameter of type `T` and should return a value of type `U`. The result sequence will have the same number of elements as the source sequence and each element will be of type `U`. 10 | 11 | ```csharp 12 | IEnumerable strings = new List { "one", "two", "three", "four" }; 13 | // Will return { 3, 3, 5, 4 } 14 | IEnumerable result = strings.Select(str => str.Length); 15 | ``` 16 | 17 | ```csharp 18 | IEnumerable points = new List 19 | { 20 | new Point(0, 0), 21 | new Point(1, 1), 22 | new Point(2, 0) 23 | }; 24 | // Will return { "(0, 0)", "(1, 1)", "(2, 0)" } 25 | IEnumerable result = points.Select(pt => $"({pt.X}, {pt.Y})"); 26 | ``` 27 | 28 | # Exercise 29 | 30 | In this exercise, try to return a sequence of strings that consist of the provided names in the form: `", "`. 31 | 32 | @[Select Exercise]({"stubs": ["CalculatedSequence1/Select1.cs"], "command": "CalculatedSequence1.UnitTest.Exercise1", "project": "exercises"}) 33 | -------------------------------------------------------------------------------- /markdowns/08_MethodsCalculateSequence/02_select.template.md: -------------------------------------------------------------------------------- 1 | # [Select(<selector>)](https://msdn.microsoft.com/en-us/library/bb548891%28v=vs.110%29.aspx) method 2 | The `Select()` method invokes the provided **selector** delegate on each element of the source `IEnumerable` sequence, and returns a new result `IEnumerable` sequence containing the output of each invocation. 3 | 4 | Wow! That's a mouthful! Let's try it this way. `Select()` takes each source element, transforms it, and returns a sequence of the transformed values. Better? 5 | 6 | > **NOTE:** Here we see LINQ showing its SQL roots again. The `Select()` method is named based on SQL syntax, but acts like the `map()` function in Java, JavaScript, Python, etc. 7 | 8 | The **selector** method should take a single parameter of type `T` and should return a value of type `U`. The result sequence will have the same number of elements as the source sequence and each element will be of type `U`. 9 | 10 | ```csharp 11 | //// EMBED: LinqCourseEmbeddedCode/Methods5.cs, Select() 1 12 | ``` 13 | 14 | ```csharp 15 | //// EMBED: LinqCourseEmbeddedCode/Methods5.cs, Select() 2 16 | ``` 17 | 18 | # Exercise 19 | 20 | In this exercise, try to return a sequence of strings that consist of the provided names in the form: `", "`. 21 | 22 | @[Select Exercise]({"stubs": ["CalculatedSequence1/Select1.cs"], "command": "CalculatedSequence1.UnitTest.Exercise1", "project": "exercises"}) 23 | -------------------------------------------------------------------------------- /markdowns/08_MethodsCalculateSequence/03_selectmany.md: -------------------------------------------------------------------------------- 1 | [//]: # (GENERATED FILE -- DO NOT EDIT) 2 | # [SelectMany(<selector>)](https://msdn.microsoft.com/en-us/library/bb534336%28v=vs.110%29.aspx) method 3 | The `SelectMany()` method is used to "flatten" a sequence in which each of the elements of the sequence is a separate, subordinate sequence. For example, `SelectMany()` can turn a two-dimensional array into a single sequence of values, as shown in this example: 4 | 5 | ```csharp 6 | int[][] arrays = { 7 | new[] {1, 2, 3}, 8 | new[] {4}, 9 | new[] {5, 6, 7, 8}, 10 | new[] {12, 14} 11 | }; 12 | // Will return { 1, 2, 3, 4, 5, 6, 7, 8, 12, 14 } 13 | IEnumerable result = arrays.SelectMany(array => array); 14 | ``` 15 | 16 | Notice that in the code above, we passed an identity lambda expression into the `SelectMany()` call. This causes the elements of the constituent arrays to be copied into the resultant sequence without alteration. 17 | 18 | You can also perform transformations on the constituent sequences, as shown in this example utilizing a list of lists: 19 | 20 | ```csharp 21 | List> lists = new List> { 22 | new List {1, 2, 3}, 23 | new List {12}, 24 | new List {5, 6, 5, 7}, 25 | new List {10, 10, 10, 12} 26 | }; 27 | // Will return { 1, 2, 3, 12, 5, 6, 7, 10, 12 } 28 | IEnumerable result = lists.SelectMany(list => list.Distinct()); 29 | ``` 30 | -------------------------------------------------------------------------------- /markdowns/08_MethodsCalculateSequence/03_selectmany.template.md: -------------------------------------------------------------------------------- 1 | # [SelectMany(<selector>)](https://msdn.microsoft.com/en-us/library/bb534336%28v=vs.110%29.aspx) method 2 | The `SelectMany()` method is used to "flatten" a sequence in which each of the elements of the sequence is a separate, subordinate sequence. For example, `SelectMany()` can turn a two-dimensional array into a single sequence of values, as shown in this example: 3 | 4 | ```csharp 5 | //// EMBED: LinqCourseEmbeddedCode/Methods5.cs, SelectMany() 1 6 | ``` 7 | 8 | Notice that in the code above, we passed an identity lambda expression into the `SelectMany()` call. This causes the elements of the constituent arrays to be copied into the resultant sequence without alteration. 9 | 10 | You can also perform transformations on the constituent sequences, as shown in this example utilizing a list of lists: 11 | 12 | ```csharp 13 | //// EMBED: LinqCourseEmbeddedCode/Methods5.cs, SelectMany() 2 14 | ``` 15 | -------------------------------------------------------------------------------- /markdowns/09_AllTogether/01_together.md: -------------------------------------------------------------------------------- 1 | [//]: # (GENERATED FILE -- DO NOT EDIT) 2 | # Combined Exercise #1 3 | 4 | As we have already seen in some of the examples, LINQ methods can build on each other. Since many LINQ methods return an `IEnumerable`, subsequent LINQ methods can be called on the results. For example: 5 | 6 | ```csharp 7 | IEnumerable values = new List { "fe", "fi", "fo", "fum" }; 8 | // Will return 12 9 | int result = values 10 | .Select(word => $"{word}-{word}") // { "fe-fe", "fi-fi", ... } 11 | .Skip(2) 12 | .Select(phrase => phrase.Length) 13 | .Sum(); 14 | ``` 15 | 16 | In this exercise, combine LINQ method calls together to determine if the second sequence passed into the `TestForSquares()` method contains the squares of the elements in the first sequence. It should return `true` if the two sequences have the same number of elements and **each** element in `squares` is equal to the square of the corresponding element in `numbers`. 17 | 18 | @[Combined Exercise 1]({"stubs": ["AllTogether1/AllTogether1.cs"], "command": "AllTogether1.UnitTest.Exercise1", "project": "exercises"}) 19 | -------------------------------------------------------------------------------- /markdowns/09_AllTogether/01_together.template.md: -------------------------------------------------------------------------------- 1 | # Combined Exercise #1 2 | 3 | As we have already seen in some of the examples, LINQ methods can build on each other. Since many LINQ methods return an `IEnumerable`, subsequent LINQ methods can be called on the results. For example: 4 | 5 | ```csharp 6 | //// EMBED: LinqCourseEmbeddedCode/AllTogether1.cs, All Together 7 | ``` 8 | 9 | In this exercise, combine LINQ method calls together to determine if the second sequence passed into the `TestForSquares()` method contains the squares of the elements in the first sequence. It should return `true` if the two sequences have the same number of elements and **each** element in `squares` is equal to the square of the corresponding element in `numbers`. 10 | 11 | @[Combined Exercise 1]({"stubs": ["AllTogether1/AllTogether1.cs"], "command": "AllTogether1.UnitTest.Exercise1", "project": "exercises"}) 12 | -------------------------------------------------------------------------------- /markdowns/09_AllTogether/02_together.md: -------------------------------------------------------------------------------- 1 | [//]: # (GENERATED FILE -- DO NOT EDIT) 2 | # Combined Exercise #2 3 | 4 | Let's do one more! 5 | 6 | In this exercise, combine LINQ method calls together to do the following: 7 | - Reduce the provided list of words to only those that contain the lower-case letter 'e' in them 8 | - Sort the resulting list by alphabetical order 9 | - Obtain the last word in the sorted list 10 | - Return the string, "The last word is <word>", using the last word from the sorted list 11 | - If the sorted list is empty, return `null` 12 | 13 | @[Combined Exercise 2]({"stubs": ["AllTogether1/AllTogether2.cs"], "command": "AllTogether1.UnitTest.Exercise2", "project": "exercises"}) 14 | -------------------------------------------------------------------------------- /markdowns/09_AllTogether/02_together.template.md: -------------------------------------------------------------------------------- 1 | # Combined Exercise #2 2 | 3 | Let's do one more! 4 | 5 | In this exercise, combine LINQ method calls together to do the following: 6 | - Reduce the provided list of words to only those that contain the lower-case letter 'e' in them 7 | - Sort the resulting list by alphabetical order 8 | - Obtain the last word in the sorted list 9 | - Return the string, "The last word is <word>", using the last word from the sorted list 10 | - If the sorted list is empty, return `null` 11 | 12 | @[Combined Exercise 2]({"stubs": ["AllTogether1/AllTogether2.cs"], "command": "AllTogether1.UnitTest.Exercise2", "project": "exercises"}) 13 | -------------------------------------------------------------------------------- /markdowns/10_FinalWords/01_review.md: -------------------------------------------------------------------------------- 1 | [//]: # (GENERATED FILE -- DO NOT EDIT) 2 | # Using C# LINQ - Review 3 | Congratulations on completing the **Using C# LINQ** course! 4 | 5 | Here is a quick review of what you have learned: 6 | 7 | ## Lambda expressions 8 | Lambda expressions are defined using the lambda operator, `=>`, and allow you to define an anonymous method that can be stored and passed around in a variable. Here is an example of a lambda expression: 9 | 10 | ```csharp 11 | Func multiplyByFive = num => num * 5; 12 | // Returns 35 13 | int result = multiplyByFive(7); 14 | ``` 15 | 16 | Many LINQ methods take a method reference (called a delegate) as a parameter, and lambda expressions are a convenient way of defining these delegates. 17 | 18 | ## IEnumerable<T> 19 | LINQ methods are extensions to the `IEnumerable` interface, which is an abstraction for a sequence of values of data type `T`. Any LINQ method can be called on anything that implements `IEnumerable`, including C# arrays and collections. 20 | 21 | Any `IEnumerable` can be converted into an array or a list (which may be more convenient to work with) by calling the `ToArray()` or `ToList()` LINQ methods. 22 | 23 | ## MSDN documentation 24 | Every LINQ method is documented on MSDN at the following address: 25 | 26 | [https://msdn.microsoft.com/en-us/library/system.linq.enumerable_methods%28v=vs.110%29.aspx](https://msdn.microsoft.com/en-us/library/system.linq.enumerable_methods%28v=vs.110%29.aspx) 27 | 28 | ## Query and method syntax 29 | There are two different ways to express a LINQ statement in C#: query syntax and method syntax. Query syntax looks similar to SQL, and may be more human-readable, but not all LINQ methods are supported by query syntax. Method syntax looks more like standard C# code, and supports the full set of LINQ methods. Query syntax is converted into method syntax by the compiler. 30 | 31 | ## LINQ Methods 32 | We discussed 27 different LINQ methods, arranged into five categories: 33 | 34 | - Methods to **extract a single element** from a sequence: `First()`, `Last()`, `Single()`, `FirstOrDefault()`, `LastOrDefault()`, and `SingleOrDefault()` 35 | - Methods to **extract multiple elements** from a sequence: `Skip()`, `Take()`, `SkipWhile()`, `TakeWhile()`, `Distinct()`, `Intersect()`, and `Where()` 36 | - Methods to **change the order** of the elements in a sequence: `Reverse()`, `OrderBy()` and `ThenBy()` 37 | - Methods to **calculate a single value** based on a sequence: `Count()`, `Sum()`, `Min()`, `Max()`, `Any()`, `All()`, `SequenceEqual()`, and `Aggregate()` 38 | - Methods to **calculate a new sequence** based on a source sequence: `Cast()`, `Select()`, and `SelectMany()` 39 | -------------------------------------------------------------------------------- /markdowns/10_FinalWords/01_review.template.md: -------------------------------------------------------------------------------- 1 | # Using C# LINQ - Review 2 | Congratulations on completing the **Using C# LINQ** course! 3 | 4 | Here is a quick review of what you have learned: 5 | 6 | ## Lambda expressions 7 | Lambda expressions are defined using the lambda operator, `=>`, and allow you to define an anonymous method that can be stored and passed around in a variable. Here is an example of a lambda expression: 8 | 9 | ```csharp 10 | //// EMBED: LinqCourseEmbeddedCode/Background1.cs, Lambda 1 11 | ``` 12 | 13 | Many LINQ methods take a method reference (called a delegate) as a parameter, and lambda expressions are a convenient way of defining these delegates. 14 | 15 | ## IEnumerable<T> 16 | LINQ methods are extensions to the `IEnumerable` interface, which is an abstraction for a sequence of values of data type `T`. Any LINQ method can be called on anything that implements `IEnumerable`, including C# arrays and collections. 17 | 18 | Any `IEnumerable` can be converted into an array or a list (which may be more convenient to work with) by calling the `ToArray()` or `ToList()` LINQ methods. 19 | 20 | ## MSDN documentation 21 | Every LINQ method is documented on MSDN at the following address: 22 | 23 | [https://msdn.microsoft.com/en-us/library/system.linq.enumerable_methods%28v=vs.110%29.aspx](https://msdn.microsoft.com/en-us/library/system.linq.enumerable_methods%28v=vs.110%29.aspx) 24 | 25 | ## Query and method syntax 26 | There are two different ways to express a LINQ statement in C#: query syntax and method syntax. Query syntax looks similar to SQL, and may be more human-readable, but not all LINQ methods are supported by query syntax. Method syntax looks more like standard C# code, and supports the full set of LINQ methods. Query syntax is converted into method syntax by the compiler. 27 | 28 | ## LINQ Methods 29 | We discussed 27 different LINQ methods, arranged into five categories: 30 | 31 | - Methods to **extract a single element** from a sequence: `First()`, `Last()`, `Single()`, `FirstOrDefault()`, `LastOrDefault()`, and `SingleOrDefault()` 32 | - Methods to **extract multiple elements** from a sequence: `Skip()`, `Take()`, `SkipWhile()`, `TakeWhile()`, `Distinct()`, `Intersect()`, and `Where()` 33 | - Methods to **change the order** of the elements in a sequence: `Reverse()`, `OrderBy()` and `ThenBy()` 34 | - Methods to **calculate a single value** based on a sequence: `Count()`, `Sum()`, `Min()`, `Max()`, `Any()`, `All()`, `SequenceEqual()`, and `Aggregate()` 35 | - Methods to **calculate a new sequence** based on a source sequence: `Cast()`, `Select()`, and `SelectMany()` 36 | -------------------------------------------------------------------------------- /markdowns/10_FinalWords/02_what_next.template.md: -------------------------------------------------------------------------------- 1 | # What Next? 2 | So now that we've opened the door a bit, what's the next step? There are several directions you can go from here! 3 | 4 | ## Reinforcing 5 | Here are some other resources you can use to reinforce the information covered in this course. 6 | 7 | ### Practical LINQ (Pluralsight) 8 | Pluralsight is an excellent online training site. It offers a large number of .NET courses on a wide variety of topics, presented by very knowledgeable developers. Pluralsight is a paid resource, but it is well worth the money if you are serious about learning .NET. 9 | 10 | The [Practical LINQ](https://app.pluralsight.com/library/courses/practical-linq/table-of-contents) course, by Deborah Kurata, is very well presented and goes over much of the same material as the course you have just completed. 11 | 12 | ### 101 LINQ Samples 13 | [101 LINQ Samples](https://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b) is a set of Visual Studio solutions, provided by the Visual Studio Product Team, designed to illustrate LINQ usage. They can be opened using the free [Visual Studio Community](https://www.visualstudio.com/downloads/) IDE, and provide a great method to explore LINQ. 14 | 15 | ### CondinGame puzzles 16 | The [CodinGame](http://www.codingame.com) website provides a large suite of programming puzzles that can be solved in many languages. Here is a list of puzzles that lend themselves to a completely (or mostly) LINQ-based solution. See if you can figure them out. 17 | 18 | - [Temperatures](https://www.codingame.com/training/easy/temperatures) 19 | - [Minimal Number of Swaps](https://www.codingame.com/training/community/minimal-number-of-swaps) 20 | - [The Beautiful Sequence](https://www.codingame.com/training/community/the-beautiful-sequence) 21 | - [The Fastest](https://www.codingame.com/training/community/the-fastest) 22 | - [Gravity Tumbler](https://www.codingame.com/training/community/gravity-tumbler) 23 | 24 | ### LINQPad 25 | [LINQPad](https://www.linqpad.net) is a Windows application that lets you experiment with LINQ queries in a nice GUI environment. It requires a connection to a datasource, which requires some knowledge to setup, but if you are willing to take the time to do so, it can be a rewarding learning experience. 26 | 27 | ## Expansion 28 | Here are some resources to expand your knowledge of LINQ. They build on the information introduced in the course you have just completed. 29 | 30 | ### C# LINQ Background Topics 31 | The [C# LINQ Background Topics](https://tech.io/playgrounds/345) **tech.io** course is designed to augment the information contained in the course you have just completed. It goes into more detail on things such as delegates, the `IEnumerable` interface, and extension methods. 32 | 33 | ### C# LINQ Advanced Topics 34 | This **tech.io** course is also designed to augment the information contained in the course you have just completed. It provides some hints and precautions for how to get the most out of LINQ while avoiding some of its pitfalls. If you haven't already, you should take the **Background Topics** course before moving on to **Advanced Topics**. 35 | 36 | **Link to course TBD** 37 | 38 | ### More Effective LINQ (Pluralsight) 39 | The [More Effective LINQ](https://app.pluralsight.com/library/courses/linq-more-effective/table-of-contents) Pluralsight course, by Mark Heath, introduces more advanced LINQ usage patterns. It also gives some good information on LINQ performance and debugging. 40 | 41 | ### LINQ Architecture (Pluralsight) 42 | [LINQ Architecture](https://app.pluralsight.com/library/courses/linq-architecture/table-of-contents) is another Pluralsight course, this time by Scott Allen. It is a quick watch, and provides a lot of good ideas for what can be done in C# with the concepts introduced with LINQ. 43 | -------------------------------------------------------------------------------- /post-commit: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | yml_file=techio.yml 4 | ./remove_md_files.pl $yml_file 5 | -------------------------------------------------------------------------------- /pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | yml_file=techio.yml 4 | 5 | files="$(./embed_examples.pl $yml_file) $(./sanitize_projects.pl $yml_file)" 6 | echo $files | xargs git add 7 | -------------------------------------------------------------------------------- /projects/LinqExercises.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26430.12 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LinqExercises", "LinqExercises\LinqExercises.csproj", "{90B8646B-B99D-4FD2-85A6-901E8EB12B44}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {90B8646B-B99D-4FD2-85A6-901E8EB12B44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {90B8646B-B99D-4FD2-85A6-901E8EB12B44}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {90B8646B-B99D-4FD2-85A6-901E8EB12B44}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {90B8646B-B99D-4FD2-85A6-901E8EB12B44}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /projects/LinqExercises/AllTogether1/AllTogether1.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace AllTogether1 5 | { 6 | public class FullExercise1 7 | { 8 | // The following method should return true if each element in the squares sequence 9 | // is equal to the square of the corresponding element in the numbers sequence. 10 | // Try to write the entire method using only LINQ method calls, and without writing 11 | // any loops. 12 | public static bool TestForSquares(IEnumerable numbers, IEnumerable squares) 13 | { 14 | return numbers 15 | // .???().???() ... .???() 16 | //// START SOLUTION //// 17 | .Select(_ => _ * _).SequenceEqual(squares) 18 | //// END SOLUTION //// 19 | ; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /projects/LinqExercises/AllTogether1/AllTogether2.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace AllTogether1 5 | { 6 | public class FullExercise2 7 | { 8 | // Given a sequence of words, get rid of any that don't have the character 'e' in them, 9 | // then sort the remaining words alphabetically, then return the following phrase using 10 | // only the final word in the resulting sequence: 11 | // -> "The last word is " 12 | // If there are no words with the character 'e' in them, then return null. 13 | // 14 | // TRY to do it all using only LINQ statements. No loops or if statements. 15 | public static string GetTheLastWord(IEnumerable words) 16 | { 17 | return words 18 | // .???().???() ... .???() 19 | //// START SOLUTION //// 20 | .Where(_ => _.Contains("e")) 21 | .OrderBy(_ => _) 22 | .Select(_ => $"The last word is {_}") 23 | .LastOrDefault() 24 | //// END SOLUTION //// 25 | ; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /projects/LinqExercises/AllTogether1/UnitTest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqExercises.Utils; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | 6 | namespace AllTogether1 7 | { 8 | [TestClass] 9 | public class UnitTest 10 | { 11 | [TestMethod] 12 | public void Exercise1() 13 | { 14 | Utils.CgMessage("About to call TestForSquares({1, 2, 3, 4, 5}, {1, 4, 9, 16, 25})"); 15 | var answer = FullExercise1.TestForSquares(new[] { 1, 2, 3, 4, 5 }, new[] { 1, 4, 9, 16, 25 }); 16 | Utils.AssertAreEqual(true, answer, "{1, 2, 3, 4, 5}, {1, 4, 9, 16, 25}"); 17 | 18 | Utils.CgMessage(string.Empty); 19 | Utils.CgMessage("About to call TestForSquares({1, 2, 5}, {1, 4, 9})"); 20 | answer = FullExercise1.TestForSquares(new[] { 1, 2, 5 }, new[] { 1, 4, 9 }); 21 | Utils.AssertAreEqual(false, answer, "{1, 2, 5}, {1, 4, 9}"); 22 | 23 | Utils.CgMessage(string.Empty); 24 | Utils.CgMessage("About to call TestForSquares({12}, {144})"); 25 | answer = FullExercise1.TestForSquares(new[] { 12 }, new[] { 144 }); 26 | Utils.AssertAreEqual(true, answer, "{12}, {144}"); 27 | 28 | Utils.CgMessage(string.Empty); 29 | Utils.CgMessage("About to call TestForSquares({1, 5, 3}, {1, 25, 9, 9})"); 30 | answer = FullExercise1.TestForSquares(new[] { 1, 5, 3 }, new[] { 1, 25, 9, 9 }); 31 | Utils.AssertAreEqual(false, answer, "{1, 5, 3}, {1, 25, 9, 9}"); 32 | 33 | Utils.CgMessage(string.Empty); 34 | Utils.CgMessage("About to call TestForSquares({}, {})"); 35 | answer = FullExercise1.TestForSquares(new int[0], new int[0]); 36 | Utils.AssertAreEqual(true, answer, "{}, {}"); 37 | 38 | Utils.CgMessage(string.Empty); 39 | Utils.CgMessage("Congratulations, you did it!"); 40 | } 41 | 42 | [TestMethod] 43 | public void Exercise2() 44 | { 45 | Utils.CgMessage("About to call GetTheLastWord({\"he\",\"she\",\"it\",\"we\",\"you\",\"they\"})"); 46 | var answer = FullExercise2.GetTheLastWord(new[] { "he", "she", "it", "we", "you", "they" }); 47 | Utils.AssertAreEqual("The last word is we", answer, "{\"he\",\"she\",\"it\",\"we\",\"you\",\"they\"}"); 48 | 49 | Utils.CgMessage(string.Empty); 50 | Utils.CgMessage("About to call GetTheLastWord({\"hop\",\"top\",\"stop\",\"cop\",\"lop\",\"chop\"})"); 51 | answer = FullExercise2.GetTheLastWord(new[] { "hop", "top", "stop", "cop", "lop", "chop" }); 52 | Utils.AssertAreEqual(null, answer, "{\"hop\",\"top\",\"stop\",\"cop\",\"lop\",\"chop\"}"); 53 | 54 | Utils.CgMessage(string.Empty); 55 | Utils.CgMessage("About to call GetTheLastWord({\"elastic\",\"elaborate\",\"elephant\",\"iris\",\"ibis\",\"incredible\"})"); 56 | answer = FullExercise2.GetTheLastWord(new[] { "elastic", "elaborate", "elephant", "iris", "ibis", "incredible" }); 57 | Utils.AssertAreEqual("The last word is incredible", answer, "{\"elastic\",\"elaborate\",\"elephant\",\"iris\",\"ibis\",\"incredible\"}"); 58 | 59 | Utils.CgMessage(string.Empty); 60 | Utils.CgMessage("About to call GetTheLastWord({})"); 61 | answer = FullExercise2.GetTheLastWord(new string[0]); 62 | Utils.AssertAreEqual(null, answer, "{}"); 63 | 64 | Utils.CgMessage(string.Empty); 65 | Utils.CgMessage("Congratulations, you did it!"); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /projects/LinqExercises/Background1/LambdaExpressions1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Background1 4 | { 5 | public static class LambdaExpressions1 6 | { 7 | // Write a lambda expression that will return the next number after 8 | // the provided integer 9 | //// START UNCOMMENT //// 10 | //public static Func GetNextNumber = ??? => ???; 11 | //// END UNCOMMENT //// 12 | //// START SOLUTION //// 13 | public static Func GetNextNumber = _ => _ + 1; 14 | //// END SOLUTION //// 15 | } 16 | } -------------------------------------------------------------------------------- /projects/LinqExercises/Background1/UnitTest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqExercises.Utils; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | 6 | namespace Background1 7 | { 8 | [TestClass] 9 | public class UnitTest 10 | { 11 | [TestMethod] 12 | public void Exercise1() 13 | { 14 | Utils.CgMessage("About to test GetNextNumber(5)"); 15 | var answer = LambdaExpressions1.GetNextNumber(5).ToString(); 16 | Utils.AssertAreEqual("6", answer, "5"); 17 | 18 | Utils.CgMessage(string.Empty); 19 | Utils.CgMessage("About to test GetNextNumber(-2)"); 20 | answer = LambdaExpressions1.GetNextNumber(-2).ToString(); 21 | Utils.AssertAreEqual("-1", answer, "-2"); 22 | 23 | Utils.CgMessage(string.Empty); 24 | Utils.CgMessage("Congratulations, you did it!"); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /projects/LinqExercises/CalculatedSequence1/Select1.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace CalculatedSequence1 5 | { 6 | public static class Select1 7 | { 8 | public interface Name 9 | { 10 | string First { get; } 11 | string Middle { get; } 12 | string Last { get; } 13 | } 14 | 15 | // Return display strings in the form of ", " for 16 | // each provided name 17 | public static IEnumerable DisplayStringsForNames(IEnumerable names) 18 | { 19 | // Uncomment: 20 | // return names.???(); 21 | //// START SOLUTION //// 22 | return names.Select(_ => $"{_.Last}, {_.First}"); 23 | //// END SOLUTION //// 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /projects/LinqExercises/CalculatedSequence1/UnitTest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using LinqExercises.Utils; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | // ReSharper disable once CheckNamespace 6 | namespace CalculatedSequence1 7 | { 8 | [TestClass] 9 | public class UnitTest 10 | { 11 | [TestMethod] 12 | public void Exercise1() 13 | { 14 | var names = new List 15 | { 16 | new NameImpl("Martin Luther King"), 17 | new NameImpl("Johan Sebastian Bach"), 18 | new NameImpl("Wolfgang Amadeus Mozart"), 19 | new NameImpl("Franklin Delano Roosevelt") 20 | }; 21 | var description = "{" + string.Join(", ", names) + "}"; 22 | Utils.CgMessage($"About to test DisplayStringsForNames({description})"); 23 | var answer = Select1.DisplayStringsForNames(names); 24 | var str = string.Join("; ", answer); 25 | Utils.AssertAreEqual("King, Martin; Bach, Johan; Mozart, Wolfgang; Roosevelt, Franklin", str, description); 26 | 27 | Utils.CgMessage(string.Empty); 28 | names = new List 29 | { 30 | new NameImpl("Hillary Rodham Clinton"), 31 | new NameImpl("Edgar Allan Poe"), 32 | new NameImpl("Billie Jean King"), 33 | new NameImpl("John Fitzgerald Kennedy") 34 | }; 35 | description = "{" + string.Join(", ", names) + "}"; 36 | Utils.CgMessage($"About to test DisplayStringsForNames({description})"); 37 | answer = Select1.DisplayStringsForNames(names); 38 | str = string.Join("; ", answer); 39 | Utils.AssertAreEqual("Clinton, Hillary; Poe, Edgar; King, Billie; Kennedy, John", str, description); 40 | 41 | Utils.CgMessage(string.Empty); 42 | Utils.CgMessage("Congratulations, you did it!"); 43 | } 44 | 45 | private class NameImpl : Select1.Name 46 | { 47 | public string First { get; } 48 | 49 | public string Middle { get; } 50 | 51 | public string Last { get; } 52 | 53 | public NameImpl(string name) 54 | { 55 | var names = name.Split(' '); 56 | First = names[0]; 57 | Middle = names[1]; 58 | Last = names[2]; 59 | } 60 | 61 | public override string ToString() 62 | { 63 | return $"{First} {Middle} {Last}"; 64 | } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /projects/LinqExercises/ChangeOrder1/OrderBy1.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | //// START SOLUTION //// 5 | // ReSharper disable once CheckNamespace 6 | //// END SOLUTION //// 7 | namespace ChangeOrder1 8 | { 9 | public interface Name 10 | { 11 | //// START SOLUTION //// 12 | // ReSharper disable UnusedMemberInSuper.Global 13 | //// END SOLUTION //// 14 | string First { get; } 15 | string Middle { get; } 16 | //// START SOLUTION //// 17 | // ReSharper restore UnusedMemberInSuper.Global 18 | //// END SOLUTION //// 19 | string Last { get; } 20 | } 21 | 22 | public static class OrderBy1 23 | { 24 | // Return the provided list of names, ordered by Last, in 25 | // descending order. 26 | public static IEnumerable SortNames(IEnumerable names) 27 | { 28 | // Uncomment: 29 | // return names.???(); 30 | //// START SOLUTION //// 31 | return names.OrderByDescending(_ => _.Last); 32 | //// END SOLUTION //// 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /projects/LinqExercises/ChangeOrder1/ThenBy1.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | //// START SOLUTION //// 5 | // ReSharper disable once CheckNamespace 6 | //// END SOLUTION //// 7 | namespace ChangeOrder2 8 | { 9 | public interface Name 10 | { 11 | string First { get; } 12 | string Middle { get; } 13 | string Last { get; } 14 | } 15 | 16 | public static class ThenBy1 17 | { 18 | // Return the provided list of names, ordered by Last, then 19 | // First, then Middle 20 | public static IEnumerable SortNames(IEnumerable names) 21 | { 22 | // Uncomment: 23 | // return names.???(); 24 | //// START SOLUTION //// 25 | return names.OrderBy(_ => _.Last).ThenBy(_ => _.First).ThenBy(_ => _.Middle); 26 | //// END SOLUTION //// 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /projects/LinqExercises/LinqExercises.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp1.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /projects/LinqExercises/MethodSyntax1/MethodSyntax1.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace MethodSyntax1 5 | { 6 | public static class MethodSyntax1 7 | { 8 | public static IEnumerable FilterAndSort(IEnumerable inValues, string pattern) 9 | { 10 | return inValues 11 | //// START SOLUTION //// 12 | .Where(_ => _.Contains(pattern)) 13 | .OrderBy(_ => _) 14 | //// END SOLUTION //// 15 | // LINQ method calls here 16 | ; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /projects/LinqExercises/MethodSyntax1/UnitTest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using LinqExercises.Utils; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace MethodSyntax1 6 | { 7 | [TestClass] 8 | public class UnitTest 9 | { 10 | [TestMethod] 11 | public void Exercise1() 12 | { 13 | Utils.CgMessage("About to test FilterAndSort({foo, bar, goo, onion}, oo)"); 14 | var answer = MethodSyntax1.FilterAndSort(new List {"foo", "bar", "goo", "onion"}, "oo"); 15 | Utils.AssertAreEqual("foo, goo", string.Join(", ", answer), "{foo, bar, goo, onion}, oo"); 16 | 17 | Utils.CgMessage(string.Empty); 18 | Utils.CgMessage("About to test FilterAndSort({abc, bca, cba, aaa}, a)"); 19 | answer = MethodSyntax1.FilterAndSort(new List { "abc", "bca", "cba", "aaa" }, "a"); 20 | Utils.AssertAreEqual("aaa, abc, bca, cba", string.Join(", ", answer), "{abc, bca, cba, aaa}, a"); 21 | 22 | Utils.CgMessage(string.Empty); 23 | Utils.CgMessage("About to test FilterAndSort({pointer, reference, structure, integer}, er)"); 24 | answer = MethodSyntax1.FilterAndSort(new List { "pointer", "reference", "structure", "integer" }, "er"); 25 | Utils.AssertAreEqual("integer, pointer, reference", string.Join(", ", answer), "{pointer, reference, structure, integer}, er"); 26 | 27 | Utils.CgMessage(string.Empty); 28 | Utils.CgMessage("Congratulations, you did it!"); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /projects/LinqExercises/MultipleValue1/DistinctIntersectWhere1.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace MultipleValue1 5 | { 6 | public static class DistinctIntersectWhere1 7 | { 8 | // Return all distinct words that have less than four letters in them. 9 | public static IEnumerable GetDistinctShortWords( 10 | IEnumerable words) 11 | { 12 | // Uncomment: 13 | // return words.???(); 14 | //// START SOLUTION //// 15 | return words.Distinct().Where(_ => _.Length < 4); 16 | //// END SOLUTION //// 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /projects/LinqExercises/MultipleValue1/SkipTake1.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace MultipleValue1 5 | { 6 | public static class SkipTake1 7 | { 8 | // Return the 3rd, 4th, and 5th items of the provided sequence. 9 | public static IEnumerable GetThirdFourthFifthItems( 10 | IEnumerable words) 11 | { 12 | // Uncomment: 13 | // return words.???(); 14 | //// START SOLUTION //// 15 | return words.Skip(2).Take(3); 16 | //// END SOLUTION //// 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /projects/LinqExercises/MultipleValue1/SkipTakeWhile1.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace MultipleValue1 5 | { 6 | public static class Count1 7 | { 8 | // Return all words in the sequence between "start" (inclusive) 9 | // and "end" (non-inclusive) 10 | // For example, if given { "One", "start", "more", "end", "thing" } ... 11 | // this method should return { "start", "more" } 12 | public static IEnumerable GetStartThroughEnd(IEnumerable words) 13 | { 14 | // Uncomment: 15 | // return words.???(); 16 | //// START SOLUTION //// 17 | return words.SkipWhile(_ => _ != "start").TakeWhile(_ => _ != "end"); 18 | //// END SOLUTION //// 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /projects/LinqExercises/QuerySyntax1/QuerySyntax1.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace QuerySyntax1 5 | { 6 | public static class QuerySyntax1 7 | { 8 | public static IEnumerable FilterAndSort(IEnumerable inValues, string pattern) 9 | { 10 | return from value in inValues 11 | //// START SOLUTION //// 12 | where value.Contains(pattern) 13 | orderby value 14 | //// END SOLUTION //// 15 | // LINQ instructions here 16 | select value; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /projects/LinqExercises/QuerySyntax1/UnitTest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using LinqExercises.Utils; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace QuerySyntax1 6 | { 7 | [TestClass] 8 | public class UnitTest 9 | { 10 | [TestMethod] 11 | public void Exercise1() 12 | { 13 | Utils.CgMessage("About to test FilterAndSort({foo, bar, goo, onion}, oo)"); 14 | var answer = QuerySyntax1.FilterAndSort(new List {"foo", "bar", "goo", "onion"}, "oo"); 15 | Utils.AssertAreEqual("foo, goo", string.Join(", ", answer), "{foo, bar, goo, onion}, oo"); 16 | 17 | Utils.CgMessage(string.Empty); 18 | Utils.CgMessage("About to test FilterAndSort({abc, bca, cba, aaa}, a)"); 19 | answer = QuerySyntax1.FilterAndSort(new List { "abc", "bca", "cba", "aaa" }, "a"); 20 | Utils.AssertAreEqual("aaa, abc, bca, cba", string.Join(", ", answer), "{abc, bca, cba, aaa}, a"); 21 | 22 | Utils.CgMessage(string.Empty); 23 | Utils.CgMessage("About to test FilterAndSort({pointer, reference, structure, integer}, er)"); 24 | answer = QuerySyntax1.FilterAndSort(new List { "pointer", "reference", "structure", "integer" }, "er"); 25 | Utils.AssertAreEqual("integer, pointer, reference", string.Join(", ", answer), "{pointer, reference, structure, integer}, er"); 26 | 27 | Utils.CgMessage(string.Empty); 28 | Utils.CgMessage("Congratulations, you did it!"); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /projects/LinqExercises/SingleCalculatedValue1/Aggregate1.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace SingleCalculatedValue1 5 | { 6 | public static class Aggregate1 7 | { 8 | // Return the total number of characters in all words in 9 | // the source sequence 10 | public static int TotalCharactersInSequence(IEnumerable words) 11 | { 12 | // Uncomment: 13 | // return words.???(); 14 | //// START SOLUTION //// 15 | return words.Aggregate(0, (a, b) => a + b.Length); 16 | //// END SOLUTION //// 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /projects/LinqExercises/SingleCalculatedValue1/Count1.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace SingleCalculatedValue1 5 | { 6 | public static class Count1 7 | { 8 | // Return the number of strings in the provided sequence that begin with 9 | // the provided startString. 10 | public static int NumberThatStartWith(IEnumerable words, string startString) 11 | { 12 | // Uncomment: 13 | // return words.???(); 14 | //// START SOLUTION //// 15 | return words.Count(_ => _.StartsWith(startString)); 16 | //// END SOLUTION //// 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /projects/LinqExercises/SingleCalculatedValue1/MinMax1.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace SingleCalculatedValue1 5 | { 6 | public static class MinMax1 7 | { 8 | // Return the length of the shortest word 9 | public static int LengthOfShortestWord(IEnumerable words) 10 | { 11 | // Uncomment: 12 | // return words.???(); 13 | //// START SOLUTION //// 14 | return words.Min(_ => _.Length); 15 | //// END SOLUTION //// 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /projects/LinqExercises/SingleValue1/SingleValue1.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace SingleValue1 5 | { 6 | public static class SingleValue1 7 | { 8 | // Return the first word with just one letter in it, out of a sequence of words. 9 | // There will always be at least one. 10 | public static string GetFirstSingleLetterWord(IEnumerable words) 11 | { 12 | // Uncomment: 13 | // return words.???(); 14 | //// START SOLUTION //// 15 | return words.First(_ => _.Length == 1); 16 | //// END SOLUTION //// 17 | } 18 | 19 | // Return the last word that contains the substring "her" in it. 20 | // There will always be at least one. 21 | public static string GetLastWordWithHerInIt(IEnumerable words) 22 | { 23 | // Uncomment: 24 | // return words.???(); 25 | //// START SOLUTION //// 26 | return words.Last(_ => _.Contains("her")); 27 | //// END SOLUTION //// 28 | } 29 | 30 | // Return the fifth word in the sequence, if there is one. If there are 31 | // fewer than 5 words, then return null. 32 | public static string GetFifthWordIfItExists(IEnumerable words) 33 | { 34 | // Uncomment: 35 | // return words.???(); 36 | //// START SOLUTION //// 37 | return words.ElementAtOrDefault(4); 38 | //// END SOLUTION //// 39 | } 40 | 41 | // Return the last word in the sequence. If there are no words in 42 | // the sequence, return null. 43 | public static string GetLastWordIfAny(IEnumerable words) 44 | { 45 | // Uncomment: 46 | // return words.???(); 47 | //// START SOLUTION //// 48 | return words.LastOrDefault(); 49 | //// END SOLUTION //// 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /projects/LinqExercises/Utils/Utils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | namespace LinqExercises.Utils 5 | { 6 | public static class Utils 7 | { 8 | public static void CgMessage(string message) 9 | { 10 | Console.WriteLine($"TECHIO> message -channel \"exercise results\" \"{message}\""); 11 | } 12 | 13 | public static void AssertAreEqual(string expectedVal, string actualVal, string provided) 14 | { 15 | var expected = expectedVal ?? "null"; 16 | var actual = actualVal ?? "null"; 17 | 18 | if (expected != actual) 19 | { 20 | PrintDifference(expected, actual); 21 | } 22 | 23 | Assert.AreEqual(expected, actual); 24 | CgMessage($"IN: <{provided}> OUT: <{actual}>"); 25 | } 26 | 27 | public static void AssertAreEqual(bool expected, bool actual, string provided) 28 | { 29 | if (actual != expected) 30 | { 31 | CgMessage($"EXPECTED: <{expected}> GOT: <{actual}>"); 32 | } 33 | Assert.AreEqual(expected, actual); 34 | CgMessage($"IN: <{provided}> OUT: <{actual}>"); 35 | } 36 | 37 | private static void PrintDifference(string expected, string actual) 38 | { 39 | int offset1 = GetDiffOffest(expected, actual); 40 | int offset2 = expected.Length - offset1 - 1; 41 | if (offset2 < 0) offset2 = 0; 42 | var errCaret = new string(' ', offset1) + '^' + 43 | new string(' ', offset2); 44 | CgMessage($"EXPECTED: <{expected}> GOT: <{actual}>"); 45 | CgMessage($" {errCaret} {errCaret}"); 46 | } 47 | 48 | private static int GetDiffOffest(string expected, string actual) 49 | { 50 | var length = Math.Max(expected.Length, actual.Length); 51 | var ePadded = expected.PadRight(length, ' '); 52 | var aPadded = actual.PadRight(length, ' '); 53 | for (var i = 0; i < length; i++) 54 | { 55 | if (ePadded[i] != aPadded[i]) 56 | { 57 | return i; 58 | } 59 | } 60 | 61 | return 0; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /projects/LinqExercises/report.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | %%TITLE%% 7 | 8 | 28 | 29 | 30 | 31 |
32 | 33 |
34 |
35 | 36 |
37 |
38 |
39 | %%BAR_MESSAGE%% 40 |
41 |
42 |
43 | 44 |
45 |
46 | 47 |
48 |
49 | 50 | 51 | 52 | %%TABLE_HEADER 53 | 54 | 55 | 56 | %%TABLE_BODY%% 57 | 58 |
59 |
60 |
61 | 62 |
63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/AllTogether1/AllTogether1.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace AllTogether1 5 | { 6 | public class FullExercise1 7 | { 8 | // The following method should return true if each element in the squares sequence 9 | // is equal to the square of the corresponding element in the numbers sequence. 10 | // Try to write the entire method using only LINQ method calls, and without writing 11 | // any loops. 12 | public static bool TestForSquares(IEnumerable numbers, IEnumerable squares) 13 | { 14 | return numbers 15 | // .???().???() ... .???() 16 | ; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/AllTogether1/AllTogether1.cs.orig: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace AllTogether1 5 | { 6 | public class FullExercise1 7 | { 8 | // The following method should return true if each element in the squares sequence 9 | // is equal to the square of the corresponding element in the numbers sequence. 10 | // Try to write the entire method using only LINQ method calls, and without writing 11 | // any loops. 12 | public static bool TestForSquares(IEnumerable numbers, IEnumerable squares) 13 | { 14 | return numbers 15 | // .???().???() ... .???() 16 | //// START SOLUTION //// 17 | .Select(_ => _ * _).SequenceEqual(squares) 18 | //// END SOLUTION //// 19 | ; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/AllTogether1/AllTogether2.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace AllTogether1 5 | { 6 | public class FullExercise2 7 | { 8 | // Given a sequence of words, get rid of any that don't have the character 'e' in them, 9 | // then sort the remaining words alphabetically, then return the following phrase using 10 | // only the final word in the resulting sequence: 11 | // -> "The last word is " 12 | // If there are no words with the character 'e' in them, then return null. 13 | // 14 | // TRY to do it all using only LINQ statements. No loops or if statements. 15 | public static string GetTheLastWord(IEnumerable words) 16 | { 17 | return words 18 | // .???().???() ... .???() 19 | ; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/AllTogether1/AllTogether2.cs.orig: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace AllTogether1 5 | { 6 | public class FullExercise2 7 | { 8 | // Given a sequence of words, get rid of any that don't have the character 'e' in them, 9 | // then sort the remaining words alphabetically, then return the following phrase using 10 | // only the final word in the resulting sequence: 11 | // -> "The last word is " 12 | // If there are no words with the character 'e' in them, then return null. 13 | // 14 | // TRY to do it all using only LINQ statements. No loops or if statements. 15 | public static string GetTheLastWord(IEnumerable words) 16 | { 17 | return words 18 | // .???().???() ... .???() 19 | //// START SOLUTION //// 20 | .Where(_ => _.Contains("e")) 21 | .OrderBy(_ => _) 22 | .Select(_ => $"The last word is {_}") 23 | .LastOrDefault() 24 | //// END SOLUTION //// 25 | ; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/AllTogether1/UnitTest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqExercises.Utils; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | 6 | namespace AllTogether1 7 | { 8 | [TestClass] 9 | public class UnitTest 10 | { 11 | [TestMethod] 12 | public void Exercise1() 13 | { 14 | Utils.CgMessage("About to call TestForSquares({1, 2, 3, 4, 5}, {1, 4, 9, 16, 25})"); 15 | var answer = FullExercise1.TestForSquares(new[] { 1, 2, 3, 4, 5 }, new[] { 1, 4, 9, 16, 25 }); 16 | Utils.AssertAreEqual(true, answer, "{1, 2, 3, 4, 5}, {1, 4, 9, 16, 25}"); 17 | 18 | Utils.CgMessage(string.Empty); 19 | Utils.CgMessage("About to call TestForSquares({1, 2, 5}, {1, 4, 9})"); 20 | answer = FullExercise1.TestForSquares(new[] { 1, 2, 5 }, new[] { 1, 4, 9 }); 21 | Utils.AssertAreEqual(false, answer, "{1, 2, 5}, {1, 4, 9}"); 22 | 23 | Utils.CgMessage(string.Empty); 24 | Utils.CgMessage("About to call TestForSquares({12}, {144})"); 25 | answer = FullExercise1.TestForSquares(new[] { 12 }, new[] { 144 }); 26 | Utils.AssertAreEqual(true, answer, "{12}, {144}"); 27 | 28 | Utils.CgMessage(string.Empty); 29 | Utils.CgMessage("About to call TestForSquares({1, 5, 3}, {1, 25, 9, 9})"); 30 | answer = FullExercise1.TestForSquares(new[] { 1, 5, 3 }, new[] { 1, 25, 9, 9 }); 31 | Utils.AssertAreEqual(false, answer, "{1, 5, 3}, {1, 25, 9, 9}"); 32 | 33 | Utils.CgMessage(string.Empty); 34 | Utils.CgMessage("About to call TestForSquares({}, {})"); 35 | answer = FullExercise1.TestForSquares(new int[0], new int[0]); 36 | Utils.AssertAreEqual(true, answer, "{}, {}"); 37 | 38 | Utils.CgMessage(string.Empty); 39 | Utils.CgMessage("Congratulations, you did it!"); 40 | } 41 | 42 | [TestMethod] 43 | public void Exercise2() 44 | { 45 | Utils.CgMessage("About to call GetTheLastWord({\"he\",\"she\",\"it\",\"we\",\"you\",\"they\"})"); 46 | var answer = FullExercise2.GetTheLastWord(new[] { "he", "she", "it", "we", "you", "they" }); 47 | Utils.AssertAreEqual("The last word is we", answer, "{\"he\",\"she\",\"it\",\"we\",\"you\",\"they\"}"); 48 | 49 | Utils.CgMessage(string.Empty); 50 | Utils.CgMessage("About to call GetTheLastWord({\"hop\",\"top\",\"stop\",\"cop\",\"lop\",\"chop\"})"); 51 | answer = FullExercise2.GetTheLastWord(new[] { "hop", "top", "stop", "cop", "lop", "chop" }); 52 | Utils.AssertAreEqual(null, answer, "{\"hop\",\"top\",\"stop\",\"cop\",\"lop\",\"chop\"}"); 53 | 54 | Utils.CgMessage(string.Empty); 55 | Utils.CgMessage("About to call GetTheLastWord({\"elastic\",\"elaborate\",\"elephant\",\"iris\",\"ibis\",\"incredible\"})"); 56 | answer = FullExercise2.GetTheLastWord(new[] { "elastic", "elaborate", "elephant", "iris", "ibis", "incredible" }); 57 | Utils.AssertAreEqual("The last word is incredible", answer, "{\"elastic\",\"elaborate\",\"elephant\",\"iris\",\"ibis\",\"incredible\"}"); 58 | 59 | Utils.CgMessage(string.Empty); 60 | Utils.CgMessage("About to call GetTheLastWord({})"); 61 | answer = FullExercise2.GetTheLastWord(new string[0]); 62 | Utils.AssertAreEqual(null, answer, "{}"); 63 | 64 | Utils.CgMessage(string.Empty); 65 | Utils.CgMessage("Congratulations, you did it!"); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/AllTogether1/UnitTest.cs.orig: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqExercises.Utils; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | 6 | namespace AllTogether1 7 | { 8 | [TestClass] 9 | public class UnitTest 10 | { 11 | [TestMethod] 12 | public void Exercise1() 13 | { 14 | Utils.CgMessage("About to call TestForSquares({1, 2, 3, 4, 5}, {1, 4, 9, 16, 25})"); 15 | var answer = FullExercise1.TestForSquares(new[] { 1, 2, 3, 4, 5 }, new[] { 1, 4, 9, 16, 25 }); 16 | Utils.AssertAreEqual(true, answer, "{1, 2, 3, 4, 5}, {1, 4, 9, 16, 25}"); 17 | 18 | Utils.CgMessage(string.Empty); 19 | Utils.CgMessage("About to call TestForSquares({1, 2, 5}, {1, 4, 9})"); 20 | answer = FullExercise1.TestForSquares(new[] { 1, 2, 5 }, new[] { 1, 4, 9 }); 21 | Utils.AssertAreEqual(false, answer, "{1, 2, 5}, {1, 4, 9}"); 22 | 23 | Utils.CgMessage(string.Empty); 24 | Utils.CgMessage("About to call TestForSquares({12}, {144})"); 25 | answer = FullExercise1.TestForSquares(new[] { 12 }, new[] { 144 }); 26 | Utils.AssertAreEqual(true, answer, "{12}, {144}"); 27 | 28 | Utils.CgMessage(string.Empty); 29 | Utils.CgMessage("About to call TestForSquares({1, 5, 3}, {1, 25, 9, 9})"); 30 | answer = FullExercise1.TestForSquares(new[] { 1, 5, 3 }, new[] { 1, 25, 9, 9 }); 31 | Utils.AssertAreEqual(false, answer, "{1, 5, 3}, {1, 25, 9, 9}"); 32 | 33 | Utils.CgMessage(string.Empty); 34 | Utils.CgMessage("About to call TestForSquares({}, {})"); 35 | answer = FullExercise1.TestForSquares(new int[0], new int[0]); 36 | Utils.AssertAreEqual(true, answer, "{}, {}"); 37 | 38 | Utils.CgMessage(string.Empty); 39 | Utils.CgMessage("Congratulations, you did it!"); 40 | } 41 | 42 | [TestMethod] 43 | public void Exercise2() 44 | { 45 | Utils.CgMessage("About to call GetTheLastWord({\"he\",\"she\",\"it\",\"we\",\"you\",\"they\"})"); 46 | var answer = FullExercise2.GetTheLastWord(new[] { "he", "she", "it", "we", "you", "they" }); 47 | Utils.AssertAreEqual("The last word is we", answer, "{\"he\",\"she\",\"it\",\"we\",\"you\",\"they\"}"); 48 | 49 | Utils.CgMessage(string.Empty); 50 | Utils.CgMessage("About to call GetTheLastWord({\"hop\",\"top\",\"stop\",\"cop\",\"lop\",\"chop\"})"); 51 | answer = FullExercise2.GetTheLastWord(new[] { "hop", "top", "stop", "cop", "lop", "chop" }); 52 | Utils.AssertAreEqual(null, answer, "{\"hop\",\"top\",\"stop\",\"cop\",\"lop\",\"chop\"}"); 53 | 54 | Utils.CgMessage(string.Empty); 55 | Utils.CgMessage("About to call GetTheLastWord({\"elastic\",\"elaborate\",\"elephant\",\"iris\",\"ibis\",\"incredible\"})"); 56 | answer = FullExercise2.GetTheLastWord(new[] { "elastic", "elaborate", "elephant", "iris", "ibis", "incredible" }); 57 | Utils.AssertAreEqual("The last word is incredible", answer, "{\"elastic\",\"elaborate\",\"elephant\",\"iris\",\"ibis\",\"incredible\"}"); 58 | 59 | Utils.CgMessage(string.Empty); 60 | Utils.CgMessage("About to call GetTheLastWord({})"); 61 | answer = FullExercise2.GetTheLastWord(new string[0]); 62 | Utils.AssertAreEqual(null, answer, "{}"); 63 | 64 | Utils.CgMessage(string.Empty); 65 | Utils.CgMessage("Congratulations, you did it!"); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/Background1/LambdaExpressions1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Background1 4 | { 5 | public static class LambdaExpressions1 6 | { 7 | // Write a lambda expression that will return the next number after 8 | // the provided integer 9 | public static Func GetNextNumber = ??? => ???; 10 | } 11 | } -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/Background1/LambdaExpressions1.cs.orig: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Background1 4 | { 5 | public static class LambdaExpressions1 6 | { 7 | // Write a lambda expression that will return the next number after 8 | // the provided integer 9 | //// START UNCOMMENT //// 10 | //public static Func GetNextNumber = ??? => ???; 11 | //// END UNCOMMENT //// 12 | //// START SOLUTION //// 13 | public static Func GetNextNumber = _ => _ + 1; 14 | //// END SOLUTION //// 15 | } 16 | } -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/Background1/UnitTest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqExercises.Utils; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | 6 | namespace Background1 7 | { 8 | [TestClass] 9 | public class UnitTest 10 | { 11 | [TestMethod] 12 | public void Exercise1() 13 | { 14 | Utils.CgMessage("About to test GetNextNumber(5)"); 15 | var answer = LambdaExpressions1.GetNextNumber(5).ToString(); 16 | Utils.AssertAreEqual("6", answer, "5"); 17 | 18 | Utils.CgMessage(string.Empty); 19 | Utils.CgMessage("About to test GetNextNumber(-2)"); 20 | answer = LambdaExpressions1.GetNextNumber(-2).ToString(); 21 | Utils.AssertAreEqual("-1", answer, "-2"); 22 | 23 | Utils.CgMessage(string.Empty); 24 | Utils.CgMessage("Congratulations, you did it!"); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/Background1/UnitTest.cs.orig: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LinqExercises.Utils; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | 6 | namespace Background1 7 | { 8 | [TestClass] 9 | public class UnitTest 10 | { 11 | [TestMethod] 12 | public void Exercise1() 13 | { 14 | Utils.CgMessage("About to test GetNextNumber(5)"); 15 | var answer = LambdaExpressions1.GetNextNumber(5).ToString(); 16 | Utils.AssertAreEqual("6", answer, "5"); 17 | 18 | Utils.CgMessage(string.Empty); 19 | Utils.CgMessage("About to test GetNextNumber(-2)"); 20 | answer = LambdaExpressions1.GetNextNumber(-2).ToString(); 21 | Utils.AssertAreEqual("-1", answer, "-2"); 22 | 23 | Utils.CgMessage(string.Empty); 24 | Utils.CgMessage("Congratulations, you did it!"); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/CalculatedSequence1/Select1.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace CalculatedSequence1 5 | { 6 | public static class Select1 7 | { 8 | public interface Name 9 | { 10 | string First { get; } 11 | string Middle { get; } 12 | string Last { get; } 13 | } 14 | 15 | // Return display strings in the form of ", " for 16 | // each provided name 17 | public static IEnumerable DisplayStringsForNames(IEnumerable names) 18 | { 19 | // Uncomment: 20 | // return names.???(); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/CalculatedSequence1/Select1.cs.orig: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace CalculatedSequence1 5 | { 6 | public static class Select1 7 | { 8 | public interface Name 9 | { 10 | string First { get; } 11 | string Middle { get; } 12 | string Last { get; } 13 | } 14 | 15 | // Return display strings in the form of ", " for 16 | // each provided name 17 | public static IEnumerable DisplayStringsForNames(IEnumerable names) 18 | { 19 | // Uncomment: 20 | // return names.???(); 21 | //// START SOLUTION //// 22 | return names.Select(_ => $"{_.Last}, {_.First}"); 23 | //// END SOLUTION //// 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/CalculatedSequence1/UnitTest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using LinqExercises.Utils; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | // ReSharper disable once CheckNamespace 6 | namespace CalculatedSequence1 7 | { 8 | [TestClass] 9 | public class UnitTest 10 | { 11 | [TestMethod] 12 | public void Exercise1() 13 | { 14 | var names = new List 15 | { 16 | new NameImpl("Martin Luther King"), 17 | new NameImpl("Johan Sebastian Bach"), 18 | new NameImpl("Wolfgang Amadeus Mozart"), 19 | new NameImpl("Franklin Delano Roosevelt") 20 | }; 21 | var description = "{" + string.Join(", ", names) + "}"; 22 | Utils.CgMessage($"About to test DisplayStringsForNames({description})"); 23 | var answer = Select1.DisplayStringsForNames(names); 24 | var str = string.Join("; ", answer); 25 | Utils.AssertAreEqual("King, Martin; Bach, Johan; Mozart, Wolfgang; Roosevelt, Franklin", str, description); 26 | 27 | Utils.CgMessage(string.Empty); 28 | names = new List 29 | { 30 | new NameImpl("Hillary Rodham Clinton"), 31 | new NameImpl("Edgar Allan Poe"), 32 | new NameImpl("Billie Jean King"), 33 | new NameImpl("John Fitzgerald Kennedy") 34 | }; 35 | description = "{" + string.Join(", ", names) + "}"; 36 | Utils.CgMessage($"About to test DisplayStringsForNames({description})"); 37 | answer = Select1.DisplayStringsForNames(names); 38 | str = string.Join("; ", answer); 39 | Utils.AssertAreEqual("Clinton, Hillary; Poe, Edgar; King, Billie; Kennedy, John", str, description); 40 | 41 | Utils.CgMessage(string.Empty); 42 | Utils.CgMessage("Congratulations, you did it!"); 43 | } 44 | 45 | private class NameImpl : Select1.Name 46 | { 47 | public string First { get; } 48 | 49 | public string Middle { get; } 50 | 51 | public string Last { get; } 52 | 53 | public NameImpl(string name) 54 | { 55 | var names = name.Split(' '); 56 | First = names[0]; 57 | Middle = names[1]; 58 | Last = names[2]; 59 | } 60 | 61 | public override string ToString() 62 | { 63 | return $"{First} {Middle} {Last}"; 64 | } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/CalculatedSequence1/UnitTest.cs.orig: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using LinqExercises.Utils; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | // ReSharper disable once CheckNamespace 6 | namespace CalculatedSequence1 7 | { 8 | [TestClass] 9 | public class UnitTest 10 | { 11 | [TestMethod] 12 | public void Exercise1() 13 | { 14 | var names = new List 15 | { 16 | new NameImpl("Martin Luther King"), 17 | new NameImpl("Johan Sebastian Bach"), 18 | new NameImpl("Wolfgang Amadeus Mozart"), 19 | new NameImpl("Franklin Delano Roosevelt") 20 | }; 21 | var description = "{" + string.Join(", ", names) + "}"; 22 | Utils.CgMessage($"About to test DisplayStringsForNames({description})"); 23 | var answer = Select1.DisplayStringsForNames(names); 24 | var str = string.Join("; ", answer); 25 | Utils.AssertAreEqual("King, Martin; Bach, Johan; Mozart, Wolfgang; Roosevelt, Franklin", str, description); 26 | 27 | Utils.CgMessage(string.Empty); 28 | names = new List 29 | { 30 | new NameImpl("Hillary Rodham Clinton"), 31 | new NameImpl("Edgar Allan Poe"), 32 | new NameImpl("Billie Jean King"), 33 | new NameImpl("John Fitzgerald Kennedy") 34 | }; 35 | description = "{" + string.Join(", ", names) + "}"; 36 | Utils.CgMessage($"About to test DisplayStringsForNames({description})"); 37 | answer = Select1.DisplayStringsForNames(names); 38 | str = string.Join("; ", answer); 39 | Utils.AssertAreEqual("Clinton, Hillary; Poe, Edgar; King, Billie; Kennedy, John", str, description); 40 | 41 | Utils.CgMessage(string.Empty); 42 | Utils.CgMessage("Congratulations, you did it!"); 43 | } 44 | 45 | private class NameImpl : Select1.Name 46 | { 47 | public string First { get; } 48 | 49 | public string Middle { get; } 50 | 51 | public string Last { get; } 52 | 53 | public NameImpl(string name) 54 | { 55 | var names = name.Split(' '); 56 | First = names[0]; 57 | Middle = names[1]; 58 | Last = names[2]; 59 | } 60 | 61 | public override string ToString() 62 | { 63 | return $"{First} {Middle} {Last}"; 64 | } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/ChangeOrder1/OrderBy1.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace ChangeOrder1 5 | { 6 | public interface Name 7 | { 8 | string First { get; } 9 | string Middle { get; } 10 | string Last { get; } 11 | } 12 | 13 | public static class OrderBy1 14 | { 15 | // Return the provided list of names, ordered by Last, in 16 | // descending order. 17 | public static IEnumerable SortNames(IEnumerable names) 18 | { 19 | // Uncomment: 20 | // return names.???(); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/ChangeOrder1/OrderBy1.cs.orig: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | //// START SOLUTION //// 5 | // ReSharper disable once CheckNamespace 6 | //// END SOLUTION //// 7 | namespace ChangeOrder1 8 | { 9 | public interface Name 10 | { 11 | //// START SOLUTION //// 12 | // ReSharper disable UnusedMemberInSuper.Global 13 | //// END SOLUTION //// 14 | string First { get; } 15 | string Middle { get; } 16 | //// START SOLUTION //// 17 | // ReSharper restore UnusedMemberInSuper.Global 18 | //// END SOLUTION //// 19 | string Last { get; } 20 | } 21 | 22 | public static class OrderBy1 23 | { 24 | // Return the provided list of names, ordered by Last, in 25 | // descending order. 26 | public static IEnumerable SortNames(IEnumerable names) 27 | { 28 | // Uncomment: 29 | // return names.???(); 30 | //// START SOLUTION //// 31 | return names.OrderByDescending(_ => _.Last); 32 | //// END SOLUTION //// 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/ChangeOrder1/ThenBy1.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace ChangeOrder2 5 | { 6 | public interface Name 7 | { 8 | string First { get; } 9 | string Middle { get; } 10 | string Last { get; } 11 | } 12 | 13 | public static class ThenBy1 14 | { 15 | // Return the provided list of names, ordered by Last, then 16 | // First, then Middle 17 | public static IEnumerable SortNames(IEnumerable names) 18 | { 19 | // Uncomment: 20 | // return names.???(); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/ChangeOrder1/ThenBy1.cs.orig: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | //// START SOLUTION //// 5 | // ReSharper disable once CheckNamespace 6 | //// END SOLUTION //// 7 | namespace ChangeOrder2 8 | { 9 | public interface Name 10 | { 11 | string First { get; } 12 | string Middle { get; } 13 | string Last { get; } 14 | } 15 | 16 | public static class ThenBy1 17 | { 18 | // Return the provided list of names, ordered by Last, then 19 | // First, then Middle 20 | public static IEnumerable SortNames(IEnumerable names) 21 | { 22 | // Uncomment: 23 | // return names.???(); 24 | //// START SOLUTION //// 25 | return names.OrderBy(_ => _.Last).ThenBy(_ => _.First).ThenBy(_ => _.Middle); 26 | //// END SOLUTION //// 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/LinqExercises.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp1.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/LinqExercises.csproj.orig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp1.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/MethodSyntax1/MethodSyntax1.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace MethodSyntax1 5 | { 6 | public static class MethodSyntax1 7 | { 8 | public static IEnumerable FilterAndSort(IEnumerable inValues, string pattern) 9 | { 10 | return inValues 11 | // LINQ method calls here 12 | ; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/MethodSyntax1/MethodSyntax1.cs.orig: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace MethodSyntax1 5 | { 6 | public static class MethodSyntax1 7 | { 8 | public static IEnumerable FilterAndSort(IEnumerable inValues, string pattern) 9 | { 10 | return inValues 11 | //// START SOLUTION //// 12 | .Where(_ => _.Contains(pattern)) 13 | .OrderBy(_ => _) 14 | //// END SOLUTION //// 15 | // LINQ method calls here 16 | ; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/MethodSyntax1/UnitTest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using LinqExercises.Utils; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace MethodSyntax1 6 | { 7 | [TestClass] 8 | public class UnitTest 9 | { 10 | [TestMethod] 11 | public void Exercise1() 12 | { 13 | Utils.CgMessage("About to test FilterAndSort({foo, bar, goo, onion}, oo)"); 14 | var answer = MethodSyntax1.FilterAndSort(new List {"foo", "bar", "goo", "onion"}, "oo"); 15 | Utils.AssertAreEqual("foo, goo", string.Join(", ", answer), "{foo, bar, goo, onion}, oo"); 16 | 17 | Utils.CgMessage(string.Empty); 18 | Utils.CgMessage("About to test FilterAndSort({abc, bca, cba, aaa}, a)"); 19 | answer = MethodSyntax1.FilterAndSort(new List { "abc", "bca", "cba", "aaa" }, "a"); 20 | Utils.AssertAreEqual("aaa, abc, bca, cba", string.Join(", ", answer), "{abc, bca, cba, aaa}, a"); 21 | 22 | Utils.CgMessage(string.Empty); 23 | Utils.CgMessage("About to test FilterAndSort({pointer, reference, structure, integer}, er)"); 24 | answer = MethodSyntax1.FilterAndSort(new List { "pointer", "reference", "structure", "integer" }, "er"); 25 | Utils.AssertAreEqual("integer, pointer, reference", string.Join(", ", answer), "{pointer, reference, structure, integer}, er"); 26 | 27 | Utils.CgMessage(string.Empty); 28 | Utils.CgMessage("Congratulations, you did it!"); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/MethodSyntax1/UnitTest.cs.orig: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using LinqExercises.Utils; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace MethodSyntax1 6 | { 7 | [TestClass] 8 | public class UnitTest 9 | { 10 | [TestMethod] 11 | public void Exercise1() 12 | { 13 | Utils.CgMessage("About to test FilterAndSort({foo, bar, goo, onion}, oo)"); 14 | var answer = MethodSyntax1.FilterAndSort(new List {"foo", "bar", "goo", "onion"}, "oo"); 15 | Utils.AssertAreEqual("foo, goo", string.Join(", ", answer), "{foo, bar, goo, onion}, oo"); 16 | 17 | Utils.CgMessage(string.Empty); 18 | Utils.CgMessage("About to test FilterAndSort({abc, bca, cba, aaa}, a)"); 19 | answer = MethodSyntax1.FilterAndSort(new List { "abc", "bca", "cba", "aaa" }, "a"); 20 | Utils.AssertAreEqual("aaa, abc, bca, cba", string.Join(", ", answer), "{abc, bca, cba, aaa}, a"); 21 | 22 | Utils.CgMessage(string.Empty); 23 | Utils.CgMessage("About to test FilterAndSort({pointer, reference, structure, integer}, er)"); 24 | answer = MethodSyntax1.FilterAndSort(new List { "pointer", "reference", "structure", "integer" }, "er"); 25 | Utils.AssertAreEqual("integer, pointer, reference", string.Join(", ", answer), "{pointer, reference, structure, integer}, er"); 26 | 27 | Utils.CgMessage(string.Empty); 28 | Utils.CgMessage("Congratulations, you did it!"); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/MultipleValue1/DistinctIntersectWhere1.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace MultipleValue1 5 | { 6 | public static class DistinctIntersectWhere1 7 | { 8 | // Return all distinct words that have less than four letters in them. 9 | public static IEnumerable GetDistinctShortWords( 10 | IEnumerable words) 11 | { 12 | // Uncomment: 13 | // return words.???(); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/MultipleValue1/DistinctIntersectWhere1.cs.orig: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace MultipleValue1 5 | { 6 | public static class DistinctIntersectWhere1 7 | { 8 | // Return all distinct words that have less than four letters in them. 9 | public static IEnumerable GetDistinctShortWords( 10 | IEnumerable words) 11 | { 12 | // Uncomment: 13 | // return words.???(); 14 | //// START SOLUTION //// 15 | return words.Distinct().Where(_ => _.Length < 4); 16 | //// END SOLUTION //// 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/MultipleValue1/SkipTake1.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace MultipleValue1 5 | { 6 | public static class SkipTake1 7 | { 8 | // Return the 3rd, 4th, and 5th items of the provided sequence. 9 | public static IEnumerable GetThirdFourthFifthItems( 10 | IEnumerable words) 11 | { 12 | // Uncomment: 13 | // return words.???(); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/MultipleValue1/SkipTake1.cs.orig: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace MultipleValue1 5 | { 6 | public static class SkipTake1 7 | { 8 | // Return the 3rd, 4th, and 5th items of the provided sequence. 9 | public static IEnumerable GetThirdFourthFifthItems( 10 | IEnumerable words) 11 | { 12 | // Uncomment: 13 | // return words.???(); 14 | //// START SOLUTION //// 15 | return words.Skip(2).Take(3); 16 | //// END SOLUTION //// 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/MultipleValue1/SkipTakeWhile1.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace MultipleValue1 5 | { 6 | public static class Count1 7 | { 8 | // Return all words in the sequence between "start" (inclusive) 9 | // and "end" (non-inclusive) 10 | // For example, if given { "One", "start", "more", "end", "thing" } ... 11 | // this method should return { "start", "more" } 12 | public static IEnumerable GetStartThroughEnd(IEnumerable words) 13 | { 14 | // Uncomment: 15 | // return words.???(); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/MultipleValue1/SkipTakeWhile1.cs.orig: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace MultipleValue1 5 | { 6 | public static class Count1 7 | { 8 | // Return all words in the sequence between "start" (inclusive) 9 | // and "end" (non-inclusive) 10 | // For example, if given { "One", "start", "more", "end", "thing" } ... 11 | // this method should return { "start", "more" } 12 | public static IEnumerable GetStartThroughEnd(IEnumerable words) 13 | { 14 | // Uncomment: 15 | // return words.???(); 16 | //// START SOLUTION //// 17 | return words.SkipWhile(_ => _ != "start").TakeWhile(_ => _ != "end"); 18 | //// END SOLUTION //// 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/QuerySyntax1/QuerySyntax1.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace QuerySyntax1 5 | { 6 | public static class QuerySyntax1 7 | { 8 | public static IEnumerable FilterAndSort(IEnumerable inValues, string pattern) 9 | { 10 | return from value in inValues 11 | // LINQ instructions here 12 | select value; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/QuerySyntax1/QuerySyntax1.cs.orig: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace QuerySyntax1 5 | { 6 | public static class QuerySyntax1 7 | { 8 | public static IEnumerable FilterAndSort(IEnumerable inValues, string pattern) 9 | { 10 | return from value in inValues 11 | //// START SOLUTION //// 12 | where value.Contains(pattern) 13 | orderby value 14 | //// END SOLUTION //// 15 | // LINQ instructions here 16 | select value; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/QuerySyntax1/UnitTest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using LinqExercises.Utils; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace QuerySyntax1 6 | { 7 | [TestClass] 8 | public class UnitTest 9 | { 10 | [TestMethod] 11 | public void Exercise1() 12 | { 13 | Utils.CgMessage("About to test FilterAndSort({foo, bar, goo, onion}, oo)"); 14 | var answer = QuerySyntax1.FilterAndSort(new List {"foo", "bar", "goo", "onion"}, "oo"); 15 | Utils.AssertAreEqual("foo, goo", string.Join(", ", answer), "{foo, bar, goo, onion}, oo"); 16 | 17 | Utils.CgMessage(string.Empty); 18 | Utils.CgMessage("About to test FilterAndSort({abc, bca, cba, aaa}, a)"); 19 | answer = QuerySyntax1.FilterAndSort(new List { "abc", "bca", "cba", "aaa" }, "a"); 20 | Utils.AssertAreEqual("aaa, abc, bca, cba", string.Join(", ", answer), "{abc, bca, cba, aaa}, a"); 21 | 22 | Utils.CgMessage(string.Empty); 23 | Utils.CgMessage("About to test FilterAndSort({pointer, reference, structure, integer}, er)"); 24 | answer = QuerySyntax1.FilterAndSort(new List { "pointer", "reference", "structure", "integer" }, "er"); 25 | Utils.AssertAreEqual("integer, pointer, reference", string.Join(", ", answer), "{pointer, reference, structure, integer}, er"); 26 | 27 | Utils.CgMessage(string.Empty); 28 | Utils.CgMessage("Congratulations, you did it!"); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/QuerySyntax1/UnitTest.cs.orig: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using LinqExercises.Utils; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace QuerySyntax1 6 | { 7 | [TestClass] 8 | public class UnitTest 9 | { 10 | [TestMethod] 11 | public void Exercise1() 12 | { 13 | Utils.CgMessage("About to test FilterAndSort({foo, bar, goo, onion}, oo)"); 14 | var answer = QuerySyntax1.FilterAndSort(new List {"foo", "bar", "goo", "onion"}, "oo"); 15 | Utils.AssertAreEqual("foo, goo", string.Join(", ", answer), "{foo, bar, goo, onion}, oo"); 16 | 17 | Utils.CgMessage(string.Empty); 18 | Utils.CgMessage("About to test FilterAndSort({abc, bca, cba, aaa}, a)"); 19 | answer = QuerySyntax1.FilterAndSort(new List { "abc", "bca", "cba", "aaa" }, "a"); 20 | Utils.AssertAreEqual("aaa, abc, bca, cba", string.Join(", ", answer), "{abc, bca, cba, aaa}, a"); 21 | 22 | Utils.CgMessage(string.Empty); 23 | Utils.CgMessage("About to test FilterAndSort({pointer, reference, structure, integer}, er)"); 24 | answer = QuerySyntax1.FilterAndSort(new List { "pointer", "reference", "structure", "integer" }, "er"); 25 | Utils.AssertAreEqual("integer, pointer, reference", string.Join(", ", answer), "{pointer, reference, structure, integer}, er"); 26 | 27 | Utils.CgMessage(string.Empty); 28 | Utils.CgMessage("Congratulations, you did it!"); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/SingleCalculatedValue1/Aggregate1.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace SingleCalculatedValue1 5 | { 6 | public static class Aggregate1 7 | { 8 | // Return the total number of characters in all words in 9 | // the source sequence 10 | public static int TotalCharactersInSequence(IEnumerable words) 11 | { 12 | // Uncomment: 13 | // return words.???(); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/SingleCalculatedValue1/Aggregate1.cs.orig: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace SingleCalculatedValue1 5 | { 6 | public static class Aggregate1 7 | { 8 | // Return the total number of characters in all words in 9 | // the source sequence 10 | public static int TotalCharactersInSequence(IEnumerable words) 11 | { 12 | // Uncomment: 13 | // return words.???(); 14 | //// START SOLUTION //// 15 | return words.Aggregate(0, (a, b) => a + b.Length); 16 | //// END SOLUTION //// 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/SingleCalculatedValue1/Count1.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace SingleCalculatedValue1 5 | { 6 | public static class Count1 7 | { 8 | // Return the number of strings in the provided sequence that begin with 9 | // the provided startString. 10 | public static int NumberThatStartWith(IEnumerable words, string startString) 11 | { 12 | // Uncomment: 13 | // return words.???(); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/SingleCalculatedValue1/Count1.cs.orig: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace SingleCalculatedValue1 5 | { 6 | public static class Count1 7 | { 8 | // Return the number of strings in the provided sequence that begin with 9 | // the provided startString. 10 | public static int NumberThatStartWith(IEnumerable words, string startString) 11 | { 12 | // Uncomment: 13 | // return words.???(); 14 | //// START SOLUTION //// 15 | return words.Count(_ => _.StartsWith(startString)); 16 | //// END SOLUTION //// 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/SingleCalculatedValue1/MinMax1.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace SingleCalculatedValue1 5 | { 6 | public static class MinMax1 7 | { 8 | // Return the length of the shortest word 9 | public static int LengthOfShortestWord(IEnumerable words) 10 | { 11 | // Uncomment: 12 | // return words.???(); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/SingleCalculatedValue1/MinMax1.cs.orig: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace SingleCalculatedValue1 5 | { 6 | public static class MinMax1 7 | { 8 | // Return the length of the shortest word 9 | public static int LengthOfShortestWord(IEnumerable words) 10 | { 11 | // Uncomment: 12 | // return words.???(); 13 | //// START SOLUTION //// 14 | return words.Min(_ => _.Length); 15 | //// END SOLUTION //// 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/SingleValue1/SingleValue1.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace SingleValue1 5 | { 6 | public static class SingleValue1 7 | { 8 | // Return the first word with just one letter in it, out of a sequence of words. 9 | // There will always be at least one. 10 | public static string GetFirstSingleLetterWord(IEnumerable words) 11 | { 12 | // Uncomment: 13 | // return words.???(); 14 | } 15 | 16 | // Return the last word that contains the substring "her" in it. 17 | // There will always be at least one. 18 | public static string GetLastWordWithHerInIt(IEnumerable words) 19 | { 20 | // Uncomment: 21 | // return words.???(); 22 | } 23 | 24 | // Return the fifth word in the sequence, if there is one. If there are 25 | // fewer than 5 words, then return null. 26 | public static string GetFifthWordIfItExists(IEnumerable words) 27 | { 28 | // Uncomment: 29 | // return words.???(); 30 | } 31 | 32 | // Return the last word in the sequence. If there are no words in 33 | // the sequence, return null. 34 | public static string GetLastWordIfAny(IEnumerable words) 35 | { 36 | // Uncomment: 37 | // return words.???(); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/SingleValue1/SingleValue1.cs.orig: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace SingleValue1 5 | { 6 | public static class SingleValue1 7 | { 8 | // Return the first word with just one letter in it, out of a sequence of words. 9 | // There will always be at least one. 10 | public static string GetFirstSingleLetterWord(IEnumerable words) 11 | { 12 | // Uncomment: 13 | // return words.???(); 14 | //// START SOLUTION //// 15 | return words.First(_ => _.Length == 1); 16 | //// END SOLUTION //// 17 | } 18 | 19 | // Return the last word that contains the substring "her" in it. 20 | // There will always be at least one. 21 | public static string GetLastWordWithHerInIt(IEnumerable words) 22 | { 23 | // Uncomment: 24 | // return words.???(); 25 | //// START SOLUTION //// 26 | return words.Last(_ => _.Contains("her")); 27 | //// END SOLUTION //// 28 | } 29 | 30 | // Return the fifth word in the sequence, if there is one. If there are 31 | // fewer than 5 words, then return null. 32 | public static string GetFifthWordIfItExists(IEnumerable words) 33 | { 34 | // Uncomment: 35 | // return words.???(); 36 | //// START SOLUTION //// 37 | return words.ElementAtOrDefault(4); 38 | //// END SOLUTION //// 39 | } 40 | 41 | // Return the last word in the sequence. If there are no words in 42 | // the sequence, return null. 43 | public static string GetLastWordIfAny(IEnumerable words) 44 | { 45 | // Uncomment: 46 | // return words.???(); 47 | //// START SOLUTION //// 48 | return words.LastOrDefault(); 49 | //// END SOLUTION //// 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/Utils/Utils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | namespace LinqExercises.Utils 5 | { 6 | public static class Utils 7 | { 8 | public static void CgMessage(string message) 9 | { 10 | Console.WriteLine($"TECHIO> message -channel \"exercise results\" \"{message}\""); 11 | } 12 | 13 | public static void AssertAreEqual(string expectedVal, string actualVal, string provided) 14 | { 15 | var expected = expectedVal ?? "null"; 16 | var actual = actualVal ?? "null"; 17 | 18 | if (expected != actual) 19 | { 20 | PrintDifference(expected, actual); 21 | } 22 | 23 | Assert.AreEqual(expected, actual); 24 | CgMessage($"IN: <{provided}> OUT: <{actual}>"); 25 | } 26 | 27 | public static void AssertAreEqual(bool expected, bool actual, string provided) 28 | { 29 | if (actual != expected) 30 | { 31 | CgMessage($"EXPECTED: <{expected}> GOT: <{actual}>"); 32 | } 33 | Assert.AreEqual(expected, actual); 34 | CgMessage($"IN: <{provided}> OUT: <{actual}>"); 35 | } 36 | 37 | private static void PrintDifference(string expected, string actual) 38 | { 39 | int offset1 = GetDiffOffest(expected, actual); 40 | int offset2 = expected.Length - offset1 - 1; 41 | if (offset2 < 0) offset2 = 0; 42 | var errCaret = new string(' ', offset1) + '^' + 43 | new string(' ', offset2); 44 | CgMessage($"EXPECTED: <{expected}> GOT: <{actual}>"); 45 | CgMessage($" {errCaret} {errCaret}"); 46 | } 47 | 48 | private static int GetDiffOffest(string expected, string actual) 49 | { 50 | var length = Math.Max(expected.Length, actual.Length); 51 | var ePadded = expected.PadRight(length, ' '); 52 | var aPadded = actual.PadRight(length, ' '); 53 | for (var i = 0; i < length; i++) 54 | { 55 | if (ePadded[i] != aPadded[i]) 56 | { 57 | return i; 58 | } 59 | } 60 | 61 | return 0; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/Utils/Utils.cs.orig: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | namespace LinqExercises.Utils 5 | { 6 | public static class Utils 7 | { 8 | public static void CgMessage(string message) 9 | { 10 | Console.WriteLine($"TECHIO> message -channel \"exercise results\" \"{message}\""); 11 | } 12 | 13 | public static void AssertAreEqual(string expectedVal, string actualVal, string provided) 14 | { 15 | var expected = expectedVal ?? "null"; 16 | var actual = actualVal ?? "null"; 17 | 18 | if (expected != actual) 19 | { 20 | PrintDifference(expected, actual); 21 | } 22 | 23 | Assert.AreEqual(expected, actual); 24 | CgMessage($"IN: <{provided}> OUT: <{actual}>"); 25 | } 26 | 27 | public static void AssertAreEqual(bool expected, bool actual, string provided) 28 | { 29 | if (actual != expected) 30 | { 31 | CgMessage($"EXPECTED: <{expected}> GOT: <{actual}>"); 32 | } 33 | Assert.AreEqual(expected, actual); 34 | CgMessage($"IN: <{provided}> OUT: <{actual}>"); 35 | } 36 | 37 | private static void PrintDifference(string expected, string actual) 38 | { 39 | int offset1 = GetDiffOffest(expected, actual); 40 | int offset2 = expected.Length - offset1 - 1; 41 | if (offset2 < 0) offset2 = 0; 42 | var errCaret = new string(' ', offset1) + '^' + 43 | new string(' ', offset2); 44 | CgMessage($"EXPECTED: <{expected}> GOT: <{actual}>"); 45 | CgMessage($" {errCaret} {errCaret}"); 46 | } 47 | 48 | private static int GetDiffOffest(string expected, string actual) 49 | { 50 | var length = Math.Max(expected.Length, actual.Length); 51 | var ePadded = expected.PadRight(length, ' '); 52 | var aPadded = actual.PadRight(length, ' '); 53 | for (var i = 0; i < length; i++) 54 | { 55 | if (ePadded[i] != aPadded[i]) 56 | { 57 | return i; 58 | } 59 | } 60 | 61 | return 0; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/report.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %%TITLE%% 7 | 8 | 28 | 29 | 30 | 31 |
32 | 33 |
34 |
35 | 36 |
37 |
38 |
39 | %%BAR_MESSAGE%% 40 |
41 |
42 |
43 | 44 |
45 |
46 | 47 |
48 |
49 | 50 | 51 | 52 | %%TABLE_HEADER 53 | 54 | 55 | 56 | %%TABLE_BODY%% 57 | 58 |
59 |
60 |
61 | 62 |
63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /projects/LinqExercises_sanitized/report.html.orig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %%TITLE%% 7 | 8 | 28 | 29 | 30 | 31 |
32 | 33 |
34 |
35 | 36 |
37 |
38 |
39 | %%BAR_MESSAGE%% 40 |
41 |
42 |
43 | 44 |
45 |
46 | 47 |
48 |
49 | 50 | 51 | 52 | %%TABLE_HEADER 53 | 54 | 55 | 56 | %%TABLE_BODY%% 57 | 58 |
59 |
60 |
61 | 62 |
63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /remove_md_files.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub get_markdown_files_from($); 7 | 8 | if (scalar(@ARGV) < 1) { 9 | print "\nUsage: embed_examples.pl \n\n"; 10 | exit; 11 | } 12 | 13 | my $yml_file = $ARGV[0]; 14 | my $markdowns = get_markdown_files_from($yml_file); 15 | 16 | foreach my $file (@$markdowns) { 17 | my $template = $file; 18 | $template =~ s/\.md$/.template.md/; 19 | if (-f $template) { 20 | print "Removing generated file: $file\n"; 21 | unlink($file); 22 | } 23 | } 24 | 25 | sub get_markdown_files_from($) { 26 | my $filename = shift; 27 | 28 | open(my $fh, "<", $filename) or die "Can't open < $filename: $!"; 29 | my @lines = <$fh>; 30 | close($fh); 31 | 32 | chomp @lines; 33 | my @statement_lines = grep /statement:\s*.*\.md/, @lines; 34 | my @files = map { s/\s*statement:\s*//r } @statement_lines; 35 | return \@files; 36 | } 37 | --------------------------------------------------------------------------------