DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

配列やListを基にしてDictionaryを作成する

ここでは、配列やListをキーや値の基になるようにして、Dictionary(System.Collections.Generic名前空間)を作成する方法を紹介します。なおDictionaryクラスは、.NET Framework 2.0以降で使用できます。

ここで紹介しているサンプルでは配列を基にしてDictionaryを作成していますが、配列の代わりにコレクションを使用しても同じようにできます。

For文を使用する方法

まずはFor文を使った、何の工夫もない、基本的な方法から紹介します。この方法ならば、Dictionaryだけでなく、Hashtableでもできます。

以下の例では、2つの配列の片方がキー、もう片方が値になるようなDictionaryを作成しています。

VB.NET
コードを隠すコードを選択
'Imports System.Collections.Generic

'Dictionaryのキーにする配列
Dim keys As Integer() = New Integer() {1, 2, 3}
'Dictionaryの値にする配列
Dim vals As String() = New String() {"いち", "に", "さん"}

'Dictionaryオブジェクトを作成する
Dim dic As New Dictionary(Of Integer, String)(keys.Length)

'For文で繰り返す
Dim i As Integer
For i = 0 To keys.Length - 1
    'キーがkeys(i)である要素の値をvals(i)にする
    dic(keys(i)) = vals(i)
    '次のようにすると、キーが既に存在している時は例外がスローされる
    'dic.Add(keys(i), vals(i))
Next
C#
コードを隠すコードを選択
//using System.Collections.Generic;

//Dictionaryのキーにする配列
int[] keys = new int[] { 1, 2, 3 };
//Dictionaryの値にする配列
string[] vals = new string[] { "いち", "に", "さん" };

//Dictionaryオブジェクトを作成する
Dictionary<int, string> dic = new Dictionary<int, string>(keys.Length);

//For文で繰り返す
for (int i = 0; i < keys.Length; i++)
{
    //キーがkeys[i]である要素の値をvals[i]にする
    dic[keys[i]] = vals[i];
    //次のようにすると、キーが既に存在している時は例外がスローされる
    //dic.Add(keys[i], vals[i]);
}

ToDictionaryメソッドを使用する方法

.NET Framework 3.5以降でLINQが使えるのであれば、Enumerable.ToDictionaryメソッドを使って配列やコレクションをDictionaryに変換できます。

以下の例では、配列の要素がキー、要素のToStringメソッドの結果が値になるようなDictionaryを作成しています。

VB.NET
コードを隠すコードを選択
'Imports System.Linq
'Imports System.Collections.Generic

'基になる配列(コレクションでも可)
Dim nums As Integer() = New Integer() {1, 2, 3}

'配列の要素がキー、要素をToStringしたものが値になるようにして、
'  Dictionaryオブジェクトを作成する
Dim dic As Dictionary(Of Integer, String) = _
    nums.ToDictionary(Function(n) n, Function(n) n.ToString())
C#
コードを隠すコードを選択
//using System.Linq;
//using System.Collections.Generic;

//基になる配列(コレクションでも可)
int[] nums = new int[] { 1, 2, 3 };

//配列の要素がキー、要素をToStringしたものが値になるようにして、
//  Dictionaryオブジェクトを作成する
Dictionary<int, string> dic = nums.ToDictionary(n => n, n => n.ToString());

LINQで2つの配列からDictionaryを作成する

一番初めのFor文を使った例のように、LINQを使って2つの配列からDictionaryを作成する方法を考えてみます。

まずは、Enumerable.Zipメソッドを使ってみましょう。Zipで2つの配列から1つのシーケンスを作成して、それを使ってToDictionaryメソッドでDictionaryを作成します。

VB.NET
コードを隠すコードを選択
'Imports System.Linq
'Imports System.Collections.Generic

'Dictionaryのキーにする配列(コレクションでも可)
Dim keys As Integer() = New Integer() {1, 2, 3}
'Dictionaryの値にする配列(コレクションでも可)
Dim vals As String() = New String() {"いち", "に", "さん"}

'Zipを使って2つの配列の要素をプロパティに持つ匿名型のシーケンスを作り、
'  ToDictionaryでDictionaryを作る
Dim dic As Dictionary(Of Integer, String) = _
    keys.Zip(vals, Function(k, v) New With {k, v}) _
    .ToDictionary(Function(a) a.k, Function(a) a.v)
C#
コードを隠すコードを選択
//using System.Linq;
//using System.Collections.Generic;

//Dictionaryのキーにする配列(コレクションでも可)
int[] keys = new int[] { 1, 2, 3 };
//Dictionaryの値にする配列(コレクションでも可)
string[] vals = new string[] { "いち", "に", "さん" };

//Zipを使って2つの配列の要素をプロパティに持つ匿名型のシーケンスを作り、
//  ToDictionaryでDictionaryを作る
Dictionary<int, string> dic = keys.Zip(vals, (k, v) => new { k, v })
    .ToDictionary(a => a.k, a => a.v);

Enumerable.Selectメソッドを使うと、要素のインデックスが分かります。これを使うと、次のようになります。

VB.NET
コードを隠すコードを選択
'Imports System.Linq
'Imports System.Collections.Generic

'Dictionaryのキーにする配列(コレクションでも可)
Dim keys As Integer() = New Integer() {1, 2, 3}
'Dictionaryの値にする配列(コレクションでも可)
Dim vals As String() = New String() {"いち", "に", "さん"}

'Selectを使って2つの配列の要素をプロパティに持つ匿名型のシーケンスを作り、
'  ToDictionaryでDictionaryを作る
Dim dic As Dictionary(Of Integer, String) = _
    keys.[Select](Function(k, i) New With {k, Key .v = vals(i)}) _
    .ToDictionary(Function(a) a.k, Function(a) a.v)
C#
コードを隠すコードを選択
//using System.Linq;
//using System.Collections.Generic;

//Dictionaryのキーにする配列(コレクションでも可)
int[] keys = new int[] { 1, 2, 3 };
//Dictionaryの値にする配列(コレクションでも可)
string[] vals = new string[] { "いち", "に", "さん" };

//Selectを使って2つの配列の要素をプロパティに持つ匿名型のシーケンスを作り、
//  ToDictionaryでDictionaryを作る
Dictionary<int, string> dic = keys.Select((k, i) => new { k, v = vals[i] })
    .ToDictionary(a => a.k, a => a.v);

Enumerable.Rangeメソッドを使えば指定した範囲の整数のシーケンスを作成できますので、これを使って次のようにもできます。

VB.NET
コードを隠すコードを選択
'Imports System.Linq
'Imports System.Collections.Generic

'Dictionaryのキーにする配列(コレクションでも可)
Dim keys As Integer() = New Integer() {1, 2, 3}
'Dictionaryの値にする配列(コレクションでも可)
Dim vals As String() = New String() {"いち", "に", "さん"}

'Rangeで0から要素数までのシーケンスを作成し、ToDictionaryでDictionaryを作る
Dim dic As Dictionary(Of Integer, String) = _
    Enumerable.Range(0, keys.Length) _
    .ToDictionary(Function(i) keys(i), Function(i) vals(i))
C#
コードを隠すコードを選択
//using System.Linq;
//using System.Collections.Generic;

//Dictionaryのキーにする配列(コレクションでも可)
int[] keys = new int[] { 1, 2, 3 };
//Dictionaryの値にする配列(コレクションでも可)
string[] vals = new string[] { "いち", "に", "さん" };

//Rangeで0から要素数までのシーケンスを作成し、ToDictionaryでDictionaryを作る
Dictionary<int, string> dic = Enumerable.Range(0, keys.Length)
    .ToDictionary(i => keys[i], i => vals[i]);

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • コードの先頭に記述されている「Imports ??? がソースファイルの一番上に書かれているものとする」(C#では、「using ???; がソースファイルの一番上に書かれているものとする」)の意味が分からないという方は、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。