T[]の値をキーとしたGroupBy
Linq - group by using the elements inside an array property
https://stackoverflow.com/a/31724862/7882280
int配列をキーとするようなものは見つかりましたが、オブジェクトの配列でGroupByをするようなものは見つかりませんでした。
上記を参考に実装してみたものが以下になります。
(Utf8Jsonを使用しています。)
public class AAA
{
public int Key { get; set; }
public string Value { get; set; }
}
class Program
{
static void Main(string[] args)
{
var group = GetValues().GroupBy(x => x, new ArrayComparer<AAA>()).ToArray();
// Count:200000 Json:[{ "Key":1,"Value":"a"},{ "Key":2,"Value":"bb"}]
// Count:100000 Json:[{ "Key":1,"Value":"a"},{ "Key":2,"Value":"ccc"}]
// Count:100000 Json:[{ "Key":1,"Value":"a"},{ "Key":2,"Value":"bb"},{ "Key":3,"Value":"ccc"}]
foreach (var g in group)
{
Console.WriteLine($"Count:{g.Count()} Json:{JsonSerializer.ToJsonString(g.Key)}");
}
}
public static IEnumerable<AAA[]> GetValues()
{
for (int i = 0; i < 100000; i++)
{
yield return new AAA[]
{
new AAA { Key = 1, Value = "a" },
new AAA { Key = 2, Value = "bb" },
};
yield return new AAA[]
{
new AAA { Key = 1, Value = "a" },
new AAA { Key = 2, Value = "bb" },
};
yield return new AAA[]
{
new AAA { Key = 1, Value = "a" },
new AAA { Key = 2, Value = "ccc" },
};
yield return new AAA[]
{
new AAA { Key = 1, Value = "a" },
new AAA { Key = 2, Value = "bb" },
new AAA { Key = 3, Value = "ccc" },
};
}
}
}
class ArrayComparer<T> : IEqualityComparer<IList<T>>
{
private Dictionary<string, int> _hashes = new Dictionary<string, int>();
public bool Equals(IList<T> x, IList<T> y)
{
return true;
}
public int GetHashCode(IList<T> obj)
{
var json = JsonSerializer.ToJsonString(obj);
if (!_hashes.ContainsKey(json))
{
var hash = json.GetHashCode();
if (!_hashes.ContainsValue(hash))
{
do
{
hash++;
} while (_hashes.ContainsValue(hash));
}
_hashes.Add(json, hash);
}
return _hashes[json];
}
}
このコードは正しいですか?
また、もっと早くする方法はありますか?