0Pricing
C# Academy · レッスン

カスタムソートのためのIComparer

比較オブジェクトで別の並べ替え順を提供します。

「カスタムソートのためのIComparer」はCoddyKit上の無料C# Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC# Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C# Academyコースには全4レッスンが含まれています。

異なる方法で並べ替える

1つの型が持つ IComparable<T> による自然な順序は1つだけです。同じデータを別の方法で並べ替えるには、呼び出し側で IComparer<T> または Comparison<T> デリゲートを渡します。

IComparer<T> の実装

IComparer<T> は、Compare(x, y) メソッドを持つ独立したオブジェクトです。CompareTo と同じく、負の値、0、正の値を返す契約に従います。

using System;
using System.Collections.Generic;

public class Person
{
    public string Name;
    public int Age;
    public Person(string name, int age) { Name = name; Age = age; }
    public override string ToString() => Name + "(" + Age + ")";
}

public class ByName : IComparer<Person>
{
    public int Compare(Person x, Person y)
        => string.Compare(x.Name, y.Name, StringComparison.Ordinal);
}

public class Program
{
    public static void Main()
    {
        var people = new List<Person> { new Person("Zoe", 1), new Person("Ann", 2) };
        people.Sort(new ByName());
        Console.WriteLine(string.Join(", ", people));
    }
}

1つの型に複数のコンパレーター

複数のコンパレーターを定義し、並べ替えごとに1つを選択できます。ここでは、同じ人物のデータを、必要に応じて名前または年齢の順で並べ替えます。

using System;
using System.Collections.Generic;

public class Person
{
    public string Name;
    public int Age;
    public Person(string name, int age) { Name = name; Age = age; }
    public override string ToString() => Name + "(" + Age + ")";
}

public class ByAge : IComparer<Person>
{
    public int Compare(Person x, Person y) => x.Age.CompareTo(y.Age);
}

public class Program
{
    public static void Main()
    {
        var people = new List<Person> { new Person("Ann", 40), new Person("Bo", 20) };
        people.Sort(new ByAge());
        Console.WriteLine(string.Join(", ", people));
    }
}

Comparison<T> デリゲート

1回限りの並べ替えでは、Comparison<T> デリゲート(多くの場合はラムダ式)を使うと、クラス全体を作成するより簡潔です。List.Sort はこれを直接受け取れます。

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        var words = new List<string> { "banana", "fig", "apple" };
        // Sort by length using a Comparison<string> lambda
        words.Sort((a, b) => a.Length.CompareTo(b.Length));
        Console.WriteLine(string.Join(", ", words));
    }
}

コンパレーターで降順にする

Compare 内でオペランドの順序を入れ替えると、順序を逆にできます。これにより、型自体を変更せずに降順で並べ替えられます。

using System;
using System.Collections.Generic;

public class DescendingInt : IComparer<int>
{
    public int Compare(int x, int y) => y.CompareTo(x);
}

public class Program
{
    public static void Main()
    {
        var nums = new List<int> { 3, 1, 4, 1, 5 };
        nums.Sort(new DescendingInt());
        Console.WriteLine(string.Join(", ", nums));
    }
}

OrderBy でコンパレーターを使う

LINQ の OrderBy は第2引数として IComparer<TKey> を受け取るため、選択したキーの比較方法をカスタマイズできます。

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

public class CaseInsensitive : IComparer<string>
{
    public int Compare(string x, string y)
        => string.Compare(x, y, StringComparison.OrdinalIgnoreCase);
}

public class Program
{
    public static void Main()
    {
        var names = new[] { "bob", "Alice", "carol" };
        foreach (var n in names.OrderBy(x => x, new CaseInsensitive()))
            Console.WriteLine(n);
    }
}

複数キーの比較

コンパレーターは、優先順位に従って複数のキーで並べ替えられます。最初のキーを比較し、同じ場合は次のキーに進みます。

using System;
using System.Collections.Generic;

public class Employee
{
    public string Dept;
    public int Salary;
    public Employee(string dept, int salary) { Dept = dept; Salary = salary; }
    public override string ToString() => Dept + ":" + Salary;
}

public class ByDeptThenSalary : IComparer<Employee>
{
    public int Compare(Employee x, Employee y)
    {
        int byDept = string.Compare(x.Dept, y.Dept, StringComparison.Ordinal);
        return byDept != 0 ? byDept : x.Salary.CompareTo(y.Salary);
    }
}

public class Program
{
    public static void Main()
    {
        var staff = new List<Employee>
        {
            new Employee("IT", 50), new Employee("HR", 40), new Employee("IT", 30)
        };
        staff.Sort(new ByDeptThenSalary());
        Console.WriteLine(string.Join(", ", staff));
    }
}

Comparer.Create のショートカット

Comparer<T>.Create はラムダ式から IComparer<T> を作成します。デリゲートの簡潔さと、コンパレーターを必要とするインターフェース API の両方を利用できます。

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        var byLengthDesc = Comparer<string>.Create((a, b) => b.Length.CompareTo(a.Length));
        var words = new List<string> { "hi", "hello", "hey" };
        words.Sort(byLengthDesc);
        Console.WriteLine(string.Join(", ", words));
    }
}

コレクション間でコンパレーターを再利用する

1つのコンパレーターのインスタンスで、並べ替え、検索、順序付きセットを処理できます。1度だけ定義しておけば、使用する場所ごとに順序付けのルールを一貫させられます。

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        IComparer<int> desc = Comparer<int>.Create((a, b) => b.CompareTo(a));
        var set = new SortedSet<int>(desc) { 1, 5, 3 };
        Console.WriteLine(string.Join(", ", set));
    }
}

IComparable と IComparer の使い分け

型に組み込む1つの自然な順序には IComparable<T> を使います。呼び出し側で決める複数の代替的な順序や、状況に応じた順序には IComparer<T> または Comparison<T> を使います。

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        var nums = new List<int> { 5, 2, 8, 1 };
        nums.Sort(); // natural ascending (int is IComparable)
        Console.WriteLine(string.Join(", ", nums));
        nums.Sort((a, b) => b - a); // custom descending via delegate
        Console.WriteLine(string.Join(", ", nums));
    }
}

自分で試す

要素の型を変更せずに、コンパレーターとラムダ式を使って、1つのリストを3通りの方法で並べ替えます。

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        var words = new List<string> { "pear", "fig", "apple", "kiwi" };

        words.Sort(); // natural alphabetical
        Console.WriteLine(string.Join(", ", words));

        words.Sort((a, b) => a.Length.CompareTo(b.Length)); // by length
        Console.WriteLine(string.Join(", ", words));

        words.Sort(Comparer<string>.Create((a, b) => b.CompareTo(a))); // reverse alphabetical
        Console.WriteLine(string.Join(", ", words));
    }
}

クイックチェック

適切な順序付けの抽象化を選んでください。

まとめ

カスタムの並べ替えでは、呼び出し側からコンパレーターを渡します。

  • IComparer<T> は、負の値、0、正の値を返す契約に従って Compare(x, y) を実装します。
  • Comparison<T> デリゲートとラムダ式は、1回限りの並べ替えに適しています。
  • Comparer<T>.Create は、ラムダ式をインターフェースに橋渡しします。
  • 自然な順序には IComparable を使い、代替の順序にはコンパレーターを使います。

よくある質問

「カスタムソートのためのIComparer」レッスンは無料ですか?

はい。「カスタムソートのためのIComparer」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C# Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C# Academyコースには全4レッスンが含まれています。

「カスタムソートのためのIComparer」で何を学びますか?

比較オブジェクトで別の並べ替え順を提供します。 ブラウザで直接実行するハンズオンコードでC# Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

C# Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのC# Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。

「カスタムソートのためのIComparer」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このC# Academyレッスンでコードを書いて実行できますか?

はい。すべてのC# Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. IEquatableの実装
  2. GetHashCodeのオーバーライド
  3. IComparableの実装
  4. カスタムソートのためのIComparer
← C# Academyに戻る