Linq To Object - Exercise 1

/*  
 * Replace every 'TODO' * comment with the appropriate code to pass the tests * AND fulfill the requirements in the comments. * For all your code, don't use any loops, but Linq only to complete the tasks. */  
// Create a set of elements first holding 1.000 objects of type Person.  
// The IDs range from 0 to 999 and the items are shuffled.  
var elements = Enumerable.Range(0, 1_000)  
    .OrderBy(n => Random.Shared.Next())  
    .Select(n => new Person { Id = n })  
    .ToList();  
  
// Find the highest ID  
int id = default;  
// TODO  
Assert("Find highest ID", id == 999);  
  
// Find the element with the highest ID by choosing the element with the ID selected above  
Person person = new Person();  
// TODO  
Assert("Find element with highest ID", person.Id == 999);  
  
// Find the element with the highest ID by using the MaxBy method  
Person person2 = new Person();  
// TODO  
Assert("Find element with highest ID with MaxBy", person2.Id == 999);  
  
// Find the element with the highest ID by using the Aggregate method  
Person person3 = new Person();  
// TODO  
Assert("Find element with highest ID with Aggregate", person3.Id == 999);  
  
// Group elements by even/odd IDs  
IEnumerable<Person> peopleWithEvenIds = Enumerable.Empty<Person>();  
IEnumerable<Person> peopleWithOddIds = Enumerable.Empty<Person>();  
// TODO  
Assert("Group even/odd elements", peopleWithEvenIds.Count() == peopleWithOddIds.Count() && peopleWithEvenIds.Any());  
  
// Let's create a second set of elements of type Person.  
// This time the IDs range from 500 to 1.499,  
// meaning the list overlaps with the first set of people.  
var elements2 = Enumerable.Range(500, 1_000)  
    .OrderBy(n => Random.Shared.Next())  
    .Select(n => new Person { Id = n })  
    .ToList();  
  
// Find intersection of elements and elements2 via their IDs  
IEnumerable<Person> intersection = Enumerable.Empty<Person>();  
// TODO  
Assert("Find intersection",  
    intersection.Count() == 500  
    && intersection.Min(p => p.Id) == 500  
    && intersection.Max(p => p.Id) == 999);  
  
// Find union of elements and elements2 via their IDs, removing duplicates  
IEnumerable<Person> personUnion = Enumerable.Empty<Person>();  
// TODO  
Assert("Find union",  
    personUnion.Count() == 1_500  
    && personUnion.DistinctBy(p => p.Id).Count() == 1_500);  
  
// Let's create another set of elements.  
// This time it's objects of type Items.  
// A Person can own an Item. If so the Item's OwnerId will be equal to the Owner's ID.  
var items = Enumerable.Range(0, 1_500_000)  
    .Select(n => new Item   
{   
Id = n,   
OwnerId = Random.Shared.Next(1_499)   
    })  
    .ToList();  
  
// Make sure that every owner ID in items is an existing ID in the union of elements and elements2  
var condition = false /*TODO*/;  
Assert("Verify OwnerIds exist",   
    condition);  
  
// Join Items with their owners using a Linq Query Expression (from ... in ... join ...)  
IEnumerable<ItemMapping> itemMappings1 = Enumerable.Empty<ItemMapping>();  
// TODO  
Assert("Join tables with Linq Query Expression", itemMappings1.Count() == 1_500);  
  
// Join Items with their owners using Linq with Lambda Expressions  
IEnumerable<ItemMapping> itemMappings2 = Enumerable.Empty<ItemMapping>();  
// TODO  
Assert("Join tables with Lambda Expressions", itemMappings2.Count() == 1_500);  
  
// Make sure both approaches yield the same result  
Assert("Verify Join approaches yield same result", false /* TODO */);  
  
// Make sure the results are correct,  
// meaning an ItemMapping should only contain items  
// where the OwnerId matches the owner inside the same mapping.  
Assert("Verify Join yields correct result", false /* TODO */);  
  
// Use SelectMany to select all items from the itemMappings1 into one Enumerable  
IEnumerable<Item> selectedItemsFromMappings = Enumerable.Empty<Item>();  
// TODO  
Assert("Use select many to flatten results", selectedItemsFromMappings.DistinctBy(i => i.Id).Count() == 1_500_000);  
  
  
  
var families = new List<Family>  
{  
    new Family  
    {  
        ClanName = "Mighty Maniacs",  
        MonthlyIncome = new List<decimal>  
        {            10,  
            20  
        }  
    },    new Family  
    {  
        ClanName = "Humble Humans",  
        MonthlyIncome = new List<decimal>  
        {            50,  
            70  
        }  
    }};  
  
decimal result = families  
    .Where(f => f.ClanName.Contains("Humans"))  
    .Select(f => f.MonthlyIncome.Sum())  
    .Average();  
  
decimal result2 = families  
    .Where(f => f.ClanName.Contains("Humans"))  
    .Average(f => f.MonthlyIncome.Sum());  
  
  
////////////////////////////////////////////////////  
/// Predefined Methods and classes.  
/// Do not change!  
////////////////////////////////////////////////////  
static void Assert(string description, bool condition)  
{  
    if (condition)  
    {        Console.WriteLine($"PASSED - {description}");  
    }    else  
    {  
        Console.Error.WriteLine($"FAIL - {description}");  
    }}  
class Person  
{  
    public int Id { get; set; }  
    public string Name { get => $"Person {Id}"; }  
}  
class Family  
{  
    public string ClanName { get; set; }  
    public IEnumerable<decimal> MonthlyIncome { get; set; }  
}  
  
class FamilyMember  
{  
    public string Name { get; set; }  
}  
  
class Item  
{  
    public int Id { get; set; }  
    public string Name { get => $"Item {Id}"; }  
    public int OwnerId { get; set; }  
}  
  
class ItemMapping  
{  
    public Person Owner { get; set; }  
    public IList<Item> Items { get; set; }  
}