計算機科学のブログ

LINQ and lambdas - Get Control of your data - queries, OrderBy, GroupBy, Select, Join methods, switch expression

Head First C#: A Learner’s Guide to Real-World Programming with C# and .NET Core (Andrew Stellman(著)、Jennifer Greene(著)、O’Reilly Media)のChapter 9(LINQ and lambdas - Get Control of your data)、p.519(Exercise)の解答を求めてみる。

コード

ComicAnalyzer.cs

using System;
using System.Collections.Generic;
using System.Linq;

namespace JimmyLinq
{
    static class ComicAnalyzer
    {
        // せっかくだからこれも三項演算子を利用したLambda式に修正
        private static PriceRange CalculatePriceRange(Comic comic) =>
            Comic.Prices[comic.Issue] < 100 ? PriceRange.Cheap : PriceRange.Expensive;
        internal static IEnumerable<IGrouping<PriceRange, Comic>>
            GroupComicsByPrice(IEnumerable<Comic> catalog,
            IReadOnlyDictionary<int, decimal> prices) =>
        catalog
            .OrderBy(comic => prices[comic.Issue])
            .GroupBy(comic => CalculatePriceRange(comic));
        internal static IEnumerable<string>
            GetReviews(IEnumerable<Comic> catalog, IEnumerable<Review> reviews) =>
        catalog
            .OrderBy(comic => comic.Issue)
            .Join(reviews,
            comic => comic.Issue,
            review => review.Issue,
            (comic, review) => $"{review.Critic} rated #{review.Issue} '{comic.Name}' {review.Score}");

    }
}

コード

Program.cs

using System;

namespace JimmyLinq
{
    class MainClass
    {
        public static void Main(string[] args)
        {
            var done = false;
            while (!done)
            {
                Console.WriteLine(
                    "\nPress G to group comics by price, R to get reviews, any other key to quit\n");
                done = Console.ReadKey(true).KeyChar.ToString().ToUpper() switch
                {
                    "G" => GroupComicsByPrice(),
                    "R" => GetReviews(),
                    _ => true,
                };
            }
        }
        private static bool GroupComicsByPrice()
        {
            var groups = ComicAnalyzer.GroupComicsByPrice(Comic.Catalog, Comic.Prices);
            foreach (var group in groups)
            {
                Console.WriteLine($"{group.Key} comics:");
                foreach (var comic in group)
                {
                    Console.WriteLine(
                        $"#{comic.Issue} {comic.Name}: {Comic.Prices[comic.Issue]:c}");
                }
            }
            return false;
        }
        private static bool GetReviews()
        {
            var reviews = ComicAnalyzer.GetReviews(Comic.Catalog, Comic.Reviews);
            foreach (var review in reviews)
            {
                Console.WriteLine(review);
            }
            return false;
        }
    }
}

入出力結果(Terminal, Zsh)

Press G to group comics by price, R to get reviews, any other key to quit

Cheap comics:
#83 Tribal Tatto Madness: $25.75
#97 The Death of the Object: $35.25
#74 Black Monday: $75.00
Expensive comics:
#68 Revenge of the New Wave Freak (damaged): $250.00
#19 Rock and Roll (limited edition): $500.00
#36 Woman's Work: $650.00
#6 Johnny America vs. the Pinko: $3,600.00
#57 Hippie Madness (misprinted): $13,525.00

Press G to group comics by price, R to get reviews, any other key to quit

MuddyCritic rated #36 'Woman's Work' 37.6
RottenTornadoes rated #74 'Black Monday' 22.8
MuddyCritic rated #74 'Black Monday' 84.2
RottenTornadoes rated #83 'Tribal Tatto Madness' 89.4
MuddyCritic rated #97 'The Death of the Object' 98.1

Press G to group comics by price, R to get reviews, any other key to quit