2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[C#]DictionaryのKeyをカスタムクラス、ValueをListにする

Posted at

概要

業務にて、タイトルの通りカスタムクラスとLINQを組み合わせたDictionaryを使った実装が必要になったため、勉強と記録がてら記事作成します。

やりたいこと

ざっくり、以下のような感じです。
(実際は全然違う内容ですが、便宜上置き換えています)

  • 社員がノートに1行ずつ起票をしていく運用のノートがある。
  • ノートでは、同じ社員が複数行起票することがある。
  • このノートにおいて、各社員が何行目に起票したかを整理し、表示する。

上記において、 社員情報-記入した行のリスト という形のDictionayを使用することで対応しました。

ポイント

Dictionaryにおいて、Keyを同一とみなすためには以下を満たす必要があるようです。

  • GetHashCodeの結果が同じであること
  • Equalsの結果がtrueであること

したがって、Keyに独自のクラスを使用する場合は、上記2つの関数を適切にオーバーライドする必要があります。

実装例

以下のような感じにしました。
※とりいそぎで書いているので、最後のコンソール出力はソートせずにdictionaryに入れた順で出しちゃってます。
※foreachのループの中でループカウンタをとってくる方法は、もっといいやり方があるかも…

社員クラス

public class Employee
{
    public string id { get; set; }
    public string name { get; set; }

    // コンストラクタ
    public Employee(string id, string name)
    {
        this.id = id;
        this.name = name;
    }

    // Equalsをオーバーライド(※VisualStudioで自動生成)
    public override bool Equals(object obj)
    {
        return obj is Employee employee &&
                id == employee.id &&
                name == employee.name;
    }

    // GetHashCodeをオーバーライド(※VisualStudioで自動生成)
    public override int GetHashCode()
    {
        int hashCode = -48284730;
        hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(id);
        hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(name);
        return hashCode;
    }
}

Main

// 結果の格納先
Dictionary<Employee, List<int>> dictionary = new Dictionary<Employee, List<int>>();

// 社員群
Employee john1 = new Employee("A0001", "John");
Employee tom = new Employee("A0002", "Tom");
Employee john2 = new Employee("A0003", "John");
Employee emily = new Employee("A0004", "Emily");
Employee alex = new Employee("A0005", "Alex");

// 記帳順のリスト
List<Employee> entryList = new List<Employee>()
{
    john1,
    tom,
    john1,
    emily,
    alex,
    john2,
    john1,
    john2,
    alex
};

List<int> valueList;
int i = 0;

Console.WriteLine("--- 記帳順 ---");

// 記帳順を格納していく
foreach (Employee employee in entryList)
{
    i++;
    // dictionaryに登録済かを判定しつつ、登録済の場合はリストを取得
    if (dictionary.TryGetValue(employee, out valueList))
    {
        // 登録済の場合、リストに値を追加して更新
        valueList.Add(i);
        dictionary[employee] = valueList;
    }
    else
    {
        // 初出の場合、登録
        dictionary.Add(employee, new List<int> { i });
    }
    Console.WriteLine(string.Format("i={0}, {1}:{2}", i, employee.id, employee.name));
}

Console.WriteLine("--- 社員ごとの記録 ---");

// 結果を出力
foreach (Employee employee in dictionary.Keys)
{
    Console.WriteLine(string.Format("{0}:{1} - {2}", employee.id, employee.name, string.Join(", ", dictionary[employee])));
}

結果

--- 記帳順 ---
i=1, A0001:John
i=2, A0002:Tom
i=3, A0001:John
i=4, A0004:Emily
i=5, A0005:Alex
i=6, A0003:John
i=7, A0001:John
i=8, A0003:John
i=9, A0005:Alex
--- 社員ごとの記録 ---
A0001:John - 1, 3, 7
A0002:Tom - 2
A0004:Emily - 4
A0005:Alex - 5, 9
A0003:John - 6, 8

参考リンク

C#で自作クラス(カスタムクラス)をキーにする方法(Dictionary,HashSet)

2
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?