読者です 読者をやめる 読者になる 読者になる

Xamarin 日本語情報

Xamarin(ザマリン) の代理店だったエクセルソフト田淵のブログです。主に Xamarin に関するエントリーをアップしていきます。(なるべく正しい有益な情報を掲載していきたいと考えていますが、このブログのエントリーは所属組織の公式見解ではありませんのでご注意ください)

LINQ で任意の文字を含む/含まない(積集合/差集合)コレクションを作成する色々なやり方を教えていただいた

Xamarin Xamarin.Forms

こんにちは。エクセルソフトの田淵です。

最初は

これで色々教えてもらいました。 今日は今日で LINQ で任意の文字を含む/含まないコレクションを作成するメモ - Xamarin 日本語情報 について HashSet が良いよとコメントを頂きました。

識者の皆様に囲まれて嬉しいです涙 色々な書き方があるんだなーということで試してみましたのでメモを残しておきます。

サンプル

GitHub

準備

1000個の i の倍数を List, HashSet で用意します。

private HashSet<string> AddItems(HashSet<string> set, int i)
{
    foreach (var j in Enumerable.Range(0, 1000))
    {
        set.Add($"Item {i * j}");
    }
    return set;
}

private List<string> AddItems(List<string> list, int i)
{
    foreach (var j in Enumerable.Range(0, 1000))
    {
        list.Add($"Item {i * j}");
    }
    return list;
}

具体的には 2 の倍数と 3 の倍数で用意しました。3 の倍数で 2 の倍数をフィルタしたいと思います。

list2 = new List<string>();
AddItems(list2, 2);
hash2 = new HashSet<string>();
AddItems(hash2, 2);

filter = new HashSet<string>();
AddItems(filter, 3);

パフォーマンス調査!

2015/8/26 追記:
計測値の大半が UI 描画では?というご指摘を頂きました。確かにそうだ!orz 慣れない事するから… 別途 Xamarin.Forms で ListView の Cell により描画の違いはあるか?などエントリーを書いてみたいと思います。今回は UI もごっちゃまぜでのあまり意味のないパフォーマンス調査ということでご容赦ください…!

Any:

var res = from s2 in list2 where filter.Any(fs => s2.Equals(fs)) select s2;
foreach (var item in res)
{
    listData.Add(item);
}

Join:

var res = from s2 in list2 join fs in filter on s2 equals fs select s2;
foreach (var item in res)
{
    listData.Add(item);
}

Intersect:

var res = list2.Intersect(filter);
foreach (var item in res)
{
    listData.Add(item);
}

HashSet.IntersectWith:

hash2.IntersectWith(filter);
foreach (var item in hash2)
{
    listData.Add(item);
}

結果

折角 Xamarin.Forms でやっているので Android, iOS, Windows Phone で計測結果を出しました。

iOS

f:id:ytabuchi:20150826094100p:plain:w300 f:id:ytabuchi:20150826094054p:plain:w300
f:id:ytabuchi:20150826094048p:plain:w300 f:id:ytabuchi:20150826094043p:plain:w300

Any 平均: 406ms
Join 平均: 356ms
Intersect 平均: 366ms
HashSet 平均: 356ms

Android

f:id:ytabuchi:20150826095625p:plain:w300 f:id:ytabuchi:20150826095636p:plain:w300
f:id:ytabuchi:20150826095633p:plain:w300 f:id:ytabuchi:20150826095629p:plain:w300

Any 平均: 235ms
Join 平均: 118ms
Intersect 平均: 118ms
HashSet 平均: 111ms

Windows Phone

f:id:ytabuchi:20150826100150p:plain:w300 f:id:ytabuchi:20150826100153p:plain:w300
f:id:ytabuchi:20150826100155p:plain:w300 f:id:ytabuchi:20150826100146p:plain:w300

Any 平均: 198ms
Join 平均: 22ms
Intersect 平均: 24ms
HashSet 平均: 21ms

所感

iOS が Any でも対して遅くないのは意外でしたが、早いはずの Join、Intersect などが遅いとも言えそうです。AOT の Mono だからですかね…?

Windows Phone で Join, Intersect がめっちゃ早かったのも印象的でした。.NET に最適化されているということかなと。このあたりは流石ですね。(UI コントロールがキレイだったらよかったのに…!><)

次は

今回は 1次元配列どうしを比較しましたが、次は少しボリュームのある List, HashSet を 1次元の配列でフィルタするのに挑戦したいと思います。

参考資料

Xamarin 気になった方は

是非 ダウンロード(直接) / ダウンロード(弊社経由) して触ってみてください。 学習用リソースJXUG リンクページ に参考資料を纏めてますので併せてどうぞ。

Xamarin の情報が欲しい方はこのブログも購読いただいたりすると嬉しいです。

以上です。