(:3[kanのメモ帳]

個人ゲーム開発者kan.kikuchiのメモ的技術ブログ。月木更新でUnity関連がメイン。

(:3[kanのメモ帳]


本ブログの運営者kan.kikuchiが個人で開発したゲームです!

    

LINQの拡張メソッドの作り方と最大値(最小値)を持つ要素の取得【C#】【LINQ】【拡張メソッド】


このエントリーをはてなブックマークに追加



はじめに

LINQMaxMinを使うこと最大値最小値を取得する事が可能ですが、

//てきとうなリスト
var list = new List<int>() {1, 2, 5, 125, -52, 58, -4, 8, 100};

//最大値と最小値を取得しログ表示
Debug.Log($"Max : {list.Max()}, Min : {list.Min()}");
f:id:kan_kikuchi:20210629072806j:plain


最大値もしくは最小値を持つ要素の取得は出来ません。

//てきとうなディクショナリ
var dict = new Dictionary<string, int>() {
  {"なまえ", 0}, {"サンプル", -10}, {"文字列", 58},
  {"Key", 350}, {"てすと", 11}, {"すとりんぐ", -5}
};

//最大値を持つ要素と最小値を持つ要素を取得したかった(エラーが出る)
Debug.Log($"Max : {dict.Max()}, Min : {dict.Min()}");
f:id:kan_kikuchi:20210629073455j:plain

ArgumentException: At least one object must implement IComparable.
System.Collections.Comparer.Compare (System.Object a, System.Object b)


という事で今回は最大値または最小値を持つ要素を取得する

LINQの拡張メソッド を作ろうという感じの記事です。

Debug.Log($"Max : {dict.MaxElement(pair => pair.Value).Key}, Min : {dict.MinElement(pair => pair.Value).Key}");
f:id:kan_kikuchi:20210629073533j:plain


なお、Unity上で動かしているので、ログの表示にDebug.Logを使っています。


LINQExtension

さっそくですが最大値まは最小値を持つ要素を取得するLINQの拡張メソッド

を実装した拡張クラスLINQExtensionは以下の通りです。

なお、LINQの拡張メソッドを作るにはIEnumerableを使って拡張する感じになります。

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

/// <summary>
/// LINQの拡張クラス
/// </summary>
public static class LINQExtension {

  //=================================================================================
  //最大値、最小を持つ要素の取得
  //=================================================================================

  /// <summary>
  /// 最大値を持つ要素の取得
  /// </summary>
  public static T MaxElement<T>(this IEnumerable<T> source, Func<T, float> selector) {
    return source.OrderByDescending(selector).FirstOrDefault();
  }
  
  /// <summary>
  /// 最大値を持つ要素の取得
  /// </summary>
  public static T MinElement<T>(this IEnumerable<T> source, Func<T, float> selector) {
    return source.OrderBy(selector).FirstOrDefault();
  }
 
}


実装内容としてはシンプルで、

降順または昇順にソートして最初の一つ(なければデフォルト値)を取得するという物。


使い方としては引数のselectorで大きさを比較するための値を渡す感じです。

//てきとうなディクショナリ
var dict = new Dictionary<string, int>() {
  {"なまえ", 0}, {"サンプル", -10}, {"文字列", 58},
  {"Key", 350}, {"てすと", 11}, {"すとりんぐ", -5}
};

//Valueの最大値を持つ要素を取得し、ログで表示
KeyValuePair<string, int> maxPair = dict.MaxElement(pair => pair.Value);
Debug.Log($"最大値を持つ要素 : {maxPair.Key}, {maxPair.Value}");
f:id:kan_kikuchi:20210629074410j:plain