|
.NET TIPS
ハッシュテーブル(Dictionaryクラス)を値でソートするには?[2.0のみ、C#、VB]
デジタルアドバンテージ 遠藤 孝信
2006/04/28 |
|
|
「TIPS:ハッシュテーブル(連想配列)を使うには?(Dictionaryクラス編)」では、Dictionaryクラス(System.Collections.Generic名前空間)の利用方法について解説した。そこでも触れているように、ハッシュテーブルに格納した要素の順序は保持されない。
しかし、ハッシュテーブルの要素のソート(並べ替え)を行ってから、要素を順に処理したい場合はよくある。例えば、テキスト内の単語とその出現頻度をハッシュテーブルによりカウントしてから、出現頻度の多い順に処理したいような場合だ。
前掲のTIPSの最後にあるように、SortedDictionaryクラス(System.Collections.Generic名前空間)を使えば、コレクションの要素をキー(Key)の値でソートすることはできる。しかし、各キーに対する値(Value)でのソート方法は標準では用意されておらず、独自に実装する必要がある。
本稿では、Dictionary<string, int>クラス(VBの場合にはDictionary(Of String, Integer)クラス)を、要素の値(整数値)によりソートする場合の実装について紹介する。
Listクラスを利用したソート
ここで紹介する方法は、すべての要素の追加が完了したハッシュテーブルの全要素を最初にListクラス(System.Collections.Generic名前空間)にコピーしてから、各要素をその値でソートする方法だ。なおハッシュテーブルでは、各要素はキーと値のペアからなるKeyValuePair構造体(System.Collections.Generic名前空間)のオブジェクトで表される。
まずハッシュテーブルをListクラスのオブジェクトにコピーするには、次のようにListクラスのコンストラクタにハッシュテーブル(Dictionaryオブジェクト)を指定するだけでよい。これによりKeyValuePairオブジェクトを要素に持つリストが作成される。
List<KeyValuePair<string, int>> list = new List<KeyValuePair<string, int>>(dict);
|
Dim list As New List(Of KeyValuePair(Of String, Integer))(dict)
|
|
DictionaryオブジェクトからListオブジェクトを作成(上:C#、下:VB) |
変数dictはDictionary(string, int)クラス(VBの場合にはDictionary(Of String, Integer)クラス)のオブジェクト。 |
次に、ListクラスのSortメソッドを使用してリストのソートを行う。本稿では、要素の比較を行うメソッドを示すデリゲート(System名前空間のComparisonデリゲート)をパラメータに持つSortメソッドを利用している。
// Valueの大きい順にソート
list.Sort(hikaku);
……省略……
int hikaku(
KeyValuePair<string, int> kvp1,
KeyValuePair<string, int> kvp2)
{
return kvp2.Value - kvp1.Value;
}
|
' Valueの大きい順にソート
list.Sort(AddressOf hikaku)
……省略……
Function hikaku( _
ByVal kvp1 As KeyValuePair(Of String, Integer), _
ByVal kvp2 As KeyValuePair(Of String, Integer)) As Integer
Return kvp2.Value - kvp1.Value
End Function
|
|
ListクラスのSortメソッドを使用してリストをソート(上:C#、下:VB) |
比較を行うメソッド(上記コードではhikakuメソッド)では、メソッドのパラメータで与えられる2つのKeyValuePairオブジェクトについて、要素の値を示すValueプロパティにより値の比較を行い、その結果を0より大きい値、0、0より小さい値のいずれかで返せばよい。
以下に、これらを実装したサンプル・プログラムを示す。
ハッシュテーブルを値でソートするサンプル・プログラム
このサンプル・プログラムでは、@ITのトップページのHTMLを取得し、その内容を単語に分割してから、単語ごとの出現頻度をハッシュテーブルによりカウントする。そして、値によるソートを実装したsortByValueメソッドによりListオブジェクトを得て、その各要素を順に画面に出力する。
// sortbyvalue.cs
using System;
using System.Net;
using System.Text.RegularExpressions;
using System.Collections.Generic;
class DictionarySortByValue {
static void makeDict(Dictionary<string, int> dict) {
string html;
// HTMLの取得
using (WebClient wc = new WebClient()) {
html = wc.DownloadString("http://www.atmarkit.co.jp/");
}
// 単語に分割して、各単語の出現頻度をカウント
foreach (string s in Regex.Split(html, "\\W")) {
string word = s.Trim();
if (word != "") {
if (dict.ContainsKey(word)) {
dict[word]++;
} else {
dict[word] = 1;
}
}
}
}
static void Main() {
Dictionary<string, int> dict = new Dictionary<string, int>();
makeDict(dict);
List<KeyValuePair<string, int>> sorted = sortByValue(dict);
// sorted.Reverse(); // 逆順にする場合
foreach (KeyValuePair<string, int> kvp in sorted) {
Console.WriteLine(kvp.Key + ":" + kvp.Value);
}
// 出力例:
// a:542
// td:394
// 0:328
// width:289
// tr:284
// ……
}
static List<KeyValuePair<string, int>>
sortByValue(Dictionary<string, int> dict)
{
List<KeyValuePair<string, int>> list
= new List<KeyValuePair<string, int>>(dict);
// Valueの大きい順にソート
list.Sort(
delegate(KeyValuePair<string, int> kvp1, KeyValuePair<string, int> kvp2) {
return kvp2.Value - kvp1.Value;
});
return list;
}
}
// コンパイル方法:csc sortbyvalue.cs
|
|
ハッシュテーブルを値でソートするC#のサンプル・プログラム(sortbyvalue.cs) |
|
' sortbyvalue.vb
Imports System
Imports System.Net
Imports System.Text.RegularExpressions
Imports System.Collections.Generic
Class DictionarySortByValue
Shared Sub makeDict(ByVal dict As Dictionary(Of String, Integer))
Dim html As String
' HTMLの取得
Using wc As New WebClient()
html = wc.DownloadString("http://www.atmarkit.co.jp/")
End Using
' 単語に分割して、各単語の出現頻度をカウント
For Each s As String In Regex.Split(html, "\W")
Dim word As String = s.Trim()
If Not word = "" Then
If dict.ContainsKey(word) Then
dict(word) += 1
Else
dict(word) = 1
End If
End If
Next
End Sub
Shared Sub Main()
Dim dict As New Dictionary(Of String, Integer)
makeDict(dict)
Dim sorted As List(Of KeyValuePair(Of String, Integer)) = sortByValue(dict)
' sorted.Reverse() ' 逆順にする場合
For Each kvp As KeyValuePair(Of String, Integer) In sorted
Console.WriteLine(kvp.Key & ":" & kvp.Value)
Next
' 出力例:
' a:542
' td:394
' 0:328
' width:289
' tr:284
' ……
End Sub
Shared Function hikaku( _
ByVal kvp1 As KeyValuePair(Of String, Integer), _
ByVal kvp2 As KeyValuePair(Of String, Integer)) As Integer
' Valueの大きい順にソート
Return kvp2.Value - kvp1.Value
End Function
Shared Function sortByValue( _
ByVal dict As Dictionary(Of String, Integer)) _
As List(Of KeyValuePair(Of String, Integer))
Dim list As New List(Of KeyValuePair(Of String, Integer))(dict)
list.Sort(AddressOf hikaku)
Return list
End Function
End Class
' コンパイル方法:vbc sortbyvalue.vb
|
|
ハッシュテーブルを値でソートするVBのサンプル・プログラム(sortbyvalue.vb) |
|
なお、C#版ではSortメソッドのパラメータ部分に匿名メソッドを使用している。
汎用的なsortByValueメソッド
上記サンプル・プログラムのsortByValueメソッドでは、キーが文字列、値が整数値の要素のみしか扱えないが、ジェネリック・メソッドの仕組みを用いれば、これをもう少し汎用的に記述できる。以下にその記述例を示しておく。
static List<KeyValuePair<TKey, TValue>>
sortByValue<TKey, TValue>(IDictionary<TKey, TValue> dict)
where TValue: IComparable<TValue>
{
List<KeyValuePair<TKey, TValue>> list
= new List<KeyValuePair<TKey, TValue>>(dict);
// Valueの大きい順にソート
list.Sort(
delegate(KeyValuePair<TKey, TValue> kvp1, KeyValuePair<TKey, TValue> kvp2) {
return kvp2.Value.CompareTo(kvp1.Value);
});
return list;
}
|
Shared Function hikaku(Of TKey, TValue As IComparable(Of TValue))( _
ByVal kvp1 As KeyValuePair(Of TKey, TValue), _
ByVal kvp2 As KeyValuePair(Of TKey, TValue)) As Integer
Return kvp2.Value.CompareTo(kvp1.Value)
End Function
Shared Function sortByValue(Of TKey, TValue As IComparable(Of TValue))( _
ByVal dict As Dictionary(Of TKey, TValue)) _
As List(Of KeyValuePair(Of TKey, TValue))
Dim list As New List(Of KeyValuePair(Of TKey, TValue))(dict)
' Valueの大きい順にソート
list.Sort(AddressOf hikaku)
Return list
End Function
|
|
ジェネリック・メソッドにより記述したsortByValueメソッド(上:C#、下:VB) |
C#版ではSortメソッドのパラメータ部分に匿名メソッドを使用している。 |
このsortByValueメソッドは、要素の値(Value)の型がIComparableインターフェイス(System名前空間)を実装している場合に利用できる。文字列や基本的な数値型はこのインターフェイスを実装している。
利用可能バージョン:.NET Framework 2.0のみ
カテゴリ:クラス・ライブラリ 処理対象:コレクション
使用ライブラリ:Dictionaryクラス(System.Collections.Generic名前空間)
使用ライブラリ:KeyValuePair構造体(System.Collections.Generic名前空間)
使用ライブラリ:Listクラス(System.Collections.Generic名前空間)
使用ライブラリ:IComparableインターフェイス(System名前空間)
関連TIPS:ハッシュテーブル(連想配列)を使うには?(Dictionaryクラス編)
|
|
generated by
|
|
Insider.NET 記事ランキング
本日
月間