
Dictionaryを使っているとたまに
Value から Key を逆引きできないの?
と、思うことがあります。
3つほど方法を紹介します。後にいくほど制約はありますが、速度面で有利です。
Where & Select
LINQ の Where、Select を使って検索する方法です。
この方法は一番汎用的で、同じ値の Value が複数あっても結果を取得することができます。
サンプルでは年齢が 16 の John、Bob を取得しています。
using System;
using System.Collections.Generic;
using System.Linq;
namespace Sample
{
static class Program
{
static Dictionary<string, int> ageList;
[STAThread]
static void Main()
{
ageList = new Dictionary<string, int>()
{
//Name Age
{"John", 16},
{"Bob", 16},
{"Catty", 15},
{"Nancy", 13},
{"George", 38},
};
var keys = findNamesFromAge(16);
foreach (var key in keys)
{
Console.WriteLine($"{key}");
}
}
static IEnumerable<string> findNamesFromAge(int age)
{
return ageList.Where( d => d.Value == age ).Select( d => d.Key );
}
}
}

Value が重複しない場合
Value が必ず一意で、重複しない場合は別の方法を取ることもできます。
LINQ を使う方法
using System;
using System.Collections.Generic;
using System.Linq;
namespace Sample
{
static class Program
{
static Dictionary<string, int> ageList;
[STAThread]
static void Main()
{
ageList = new Dictionary<string, int>()
{
//Name Age
{"Bob", 16},
{"Catty", 15},
{"Nancy", 13},
{"George", 38},
};
var key = findNameFromAge(16);
Console.WriteLine($"{key}");
}
static string findNameFromAge(int age)
{
return ageList.FirstOrDefault( d => d.Value == age ).Key;
}
}
}

Age が 16 である最初の人物のみ返します。
例えば Bob の前に同じ年齢 (16) の John を入れた場合、John のみを返します。
速度を重視する場合
using System;
using System.Collections.Generic;
using System.Linq;
namespace Sample
{
static class Program
{
static Dictionary<string, int> ageList;
[STAThread]
static void Main()
{
ageList = new Dictionary<string, int>()
{
//Name Age
{"Bob", 16},
{"Catty", 15},
{"Nancy", 13},
{"George", 38},
};
Dictionary<int, string> revAgeList = new Dictionary<int, string>();
foreach (var d in ageList)
{
revAgeList.Add(d.Value, d.Key);
}
Console.WriteLine($"{revAgeList[16]}");
}
}
}

Value が検索できないなら、Key にしちゃえばいいじゃない? ということで逆引き用の Dictionary を作る方法です。データ量が多くなれば真価を発揮するかも?
ただ、一旦逆引きテーブルを作る手間があること、Age は絶対に重複してはいけないという制約がかかること、2つの条件が必要なことも付け加えておきます。
おわりに
3つ目の方法は一見面倒ですが、速度面が重要であれば検討に値します。
逆引きする回数も少なく、速度面を考慮する必要がなければ1,2番目の方法を使いましょう。



