同一インスタンスでない List を property でまとめて数える
概要
例えば、こういうスキルの class があったとして、
Skill.cs
public class Skill
{
public int Code { get; private set; }
public int Level { get; private set; }
public Skill(int code, int level)
{
Code = code;
Level = level;
}
}
同じスキル・レベルでも別インスタンスである可能性のある List<Skill>
から、同じスキル・レベルをまとめて数える IDictionary<Skill, int> SkillCountDictionary(List<Skill>)
を実装します。
テスト
SkillTest.cs
public class SkillTest
{
[Test]
public void SkillCountDictionary()
{
CollectionAssert.AreEquivalent(
Skill.SkillCountDictionary(Skills()),
Expect()
);
}
private List<Skill> Skills()
{
var skills = new List<Skill>();
skills.Add(new Skill(1, 1));
skills.Add(new Skill(1, 1));
skills.Add(new Skill(2, 1));
skills.Add(new Skill(2, 2));
skills.Add(new Skill(2, 2));
skills.Add(new Skill(2, 2));
return skills;
}
private Dictionary<Skill, int> Expect()
{
return new Dictionary<Skill, int>
{
{new Skill(1, 1), 2},
{new Skill(2, 1), 1},
{new Skill(2, 2), 3}
};
}
}
foreach で Dictionary に入れていく実装
Skill.cs
public static IDictionary<Skill, int> SkillCountDictionary(List<Skill> skills)
{
var testCountDictionary = new Dictionary<Skill, int>();
foreach (var skill in skills)
{
// csharp> dict[0]++; => System.Collections.Generic.KeyNotFoundException
if (!testCountDictionary.ContainsKey(skill))
{
testCountDictionary[skill] = 0;
}
testCountDictionary[skill]++;
}
return testCountDictionary;
}
当然通りません。
インスタンスが違うので、それぞれ別の Key になってしまいます。
IEquatable を実装する
Skill.cs
public class Skill : IEquatable<Skill>
{
public override int GetHashCode()
{
// Tuple の実装があればこっちの方がイケてる気がする
// return Tuple.Create(Code, Level).GetHashCode();
return Code.GetHashCode() ^ Level.GetHashCode();
}
bool IEquatable<Skill>.Equals(Skill other)
{
if (other == null)
{
return false;
}
return Code == other.Code && Level == other.Level;
}
通りました。けど、長い。
LINQ GroupBy を使う実装
Skill.cs
public static IDictionary<Skill, int> SkillCountDictinary(List<Skill> skills)
{
return skills.GroupBy(s => new { s.Code, s.Level })
.ToDictionary(g => g.First(), g => g.Count());
}
1行で書けました。
まとめ
- GroupBy が便利でした。
-
IEquatable<T>
は覚えておくといいかもしれない。- もうちょっと一般的な場面でも役に立ちそう。
- Tuple が欲しくなる。
Author And Source
この問題について(同一インスタンスでない List を property でまとめて数える), 我々は、より多くの情報をここで見つけました https://qiita.com/noir_neo/items/c3512bbcbdce26192559著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .