[インデックス 14975] ファイルの概要
このコミットでは、src/pkg/exp/locale/collate/sort.go と src/pkg/exp/locale/collate/sort_test.go の2つの新しいファイルが追加されています。これらのファイルは、Go言語の実験的なロケールパッケージである exp/locale/collate に、文字列のソート機能を追加するものです。
コミット
- コミットハッシュ:
34b533cd81dbad155a8e2265d91110434bbac2fb - 作者: Marcel van Lohuizen mpvl@golang.org
- 日付: 2013年1月23日 (水) 14:16:22 +0100
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/34b533cd81dbad155a8e2265d91110434bbac2fb
元コミット内容
exp/locale/collate: added functionality for sorting.
Eliminates the need for the user to fiddle with keys.
R=rsc
CC=golang-dev
https://golang.org/cl/7060051
変更の背景
このコミットの主な背景は、Go言語の exp/locale/collate パッケージ(現在の golang.org/x/text/collate パッケージの前身)における文字列のソート処理の複雑さを軽減することにあります。以前は、ロケール固有のルールに従って文字列をソートするには、ユーザーが直接「照合キー(collation keys)」を生成し、それらを比較する必要がありました。このプロセスは、特にUnicodeの複雑な特性(アクセント、大文字小文字、文字幅など)を考慮に入れると、非常に煩雑でエラーが発生しやすいものでした。
コミットメッセージにある「Eliminates the need for the user to fiddle with keys.(ユーザーがキーをいじる必要をなくす)」という文言が示す通り、この変更の目的は、照合キーの生成と管理という低レベルな詳細を抽象化し、ユーザーがより高レベルなAPIを通じて直接文字列や文字列スライスをソートできるようにすることでした。これにより、国際化されたアプリケーションでの文字列ソートの実装が大幅に簡素化され、開発者の負担が軽減されます。
前提知識の解説
照合 (Collation)
照合とは、文字列を特定の順序で並べ替えるプロセスを指します。これは単に文字コードの順序で並べることとは異なり、言語や文化に固有のルール(ロケール)に基づいて行われます。例えば、ドイツ語では「ä」は「a」と「b」の間に来ることもあれば、「ae」として扱われることもあります。また、大文字と小文字の区別、アクセント記号の有無、文字幅(全角/半角)なども照合順序に影響を与えます。
照合キー (Collation Keys)
照合キーは、文字列の照合順序をバイト列で表現したものです。複雑なUnicode文字列の比較を効率的に行うために使用されます。文字列そのものを直接比較する代わりに、まず各文字列から照合キーを生成し、そのバイト列を辞書順に比較することで、正しい照合順序を決定します。照合キーは、元の文字列のすべての照合特性(アクセント、大文字小文字、文字幅など)をエンコードしており、バイト列として比較可能であるため、高速なソートや検索が可能になります。
exp/locale/collate パッケージは、Collator 型を提供し、この Collator が特定のロケールに基づいて照合キーを生成する機能を持っています。このコミット以前は、ユーザーは Collator.Key や Collator.KeyFromString メソッドを使って照合キーを生成し、それらをGo標準ライブラリの sort パッケージと組み合わせてソートロジックを自前で実装する必要がありました。
技術的詳細
このコミットでは、exp/locale/collate パッケージにソート機能が直接統合され、ユーザーが照合キーを直接扱う必要がなくなりました。これは主に src/pkg/exp/locale/collate/sort.go に追加された新しい型とメソッドによって実現されています。
sort.go の主要な要素
-
swapperインターフェース:type swapper interface { Swap(i, j int) }これはGo標準の
sort.InterfaceのSwapメソッドと同じシグネチャを持つシンプルなインターフェースです。sorter構造体がソート対象のデータと連携するために使用されます。 -
sorter構造体:type sorter struct { buf *Buffer keys [][]byte src swapper }この構造体は、ソート処理の内部状態を管理します。
buf:Collatorが照合キーを生成する際に使用するバッファです。メモリ割り当てを削減するために再利用されます。keys: 生成された照合キー(バイトスライス)を格納するスライスです。src: ソート対象のデータがswapperインターフェースを満たす場合に、そのSwapメソッドを呼び出すために使用されます。
sorterはsort.Interface(Len, Less, Swap) を実装しており、Go標準のsort.Sort関数に渡すことができます。Len():s.keysの長さを返します。Less(i, j int) bool:s.keys[i]とs.keys[j]をバイト比較し、s.keys[i]がs.keys[j]より小さい場合にtrueを返します。これにより、照合キーの辞書順比較が実現されます。Swap(i, j int):s.keys内の要素を交換すると同時に、s.srcのSwapメソッドを呼び出して、ソート対象の元のデータも交換します。
-
Listerインターフェース:type Lister interface { Len() int Swap(i, j int) // Bytes returns the bytes of the text at index i. Bytes(i int) []byte }この新しいインターフェースは、
Collator.Sortメソッドがソート可能な任意のデータ型を抽象化するために導入されました。Go標準のsort.InterfaceにBytes(i int) []byteメソッドが追加された形です。このBytesメソッドは、指定されたインデックスの文字列のバイト表現を返します。これにより、Collatorはソート対象の文字列を取得し、それに対応する照合キーを生成できます。 -
Collatorの新しいメソッド:-
func (c *Collator) Sort(x Lister): このメソッドは、Listerインターフェースを満たす任意のデータ構造を、c(Collatorインスタンス)の照合ルールに従ってソートします。内部的には、xの各要素から照合キーを生成し、それらをsorterに格納した後、sort.Sort(c.sorter)を呼び出してソートを実行します。sorterのSwapメソッドがx.Swapを呼び出すことで、元のデータも適切に並べ替えられます。 -
func (c *Collator) Strings(x []string): このメソッドは、[]string型のスライスを、cの照合ルールに従ってソートするための便利なラッパーです。内部的には、sort.StringSlice(x)をListerとして扱い、Collator.Sortメソッドを呼び出します。これにより、一般的な文字列スライスのソートが非常に簡単になります。
-
sort_test.go
このファイルには、新しく追加されたソート機能のテストと使用例が含まれています。
ExampleCollator_Strings():Collator.Stringsメソッドを使用して文字列スライスをソートする簡単な例を示しています。TestSort():Listerインターフェースを実装したカスタム型 (sorterという名前だが、これはテスト用のヘルパー型で、collateパッケージ内のsorter構造体とは別物) を定義し、Collator.Sortメソッドが正しく機能することを確認するテストです。
コアとなるコードの変更箇所
このコミットで追加された主要なコードは以下の2つのファイルです。
-
src/pkg/exp/locale/collate/sort.go:swapperインターフェースの定義sorter構造体の定義とsort.Interfaceの実装 (Len,Less,Swapメソッド)Listerインターフェースの定義Collator型にSort(x Lister)メソッドの追加Collator型にStrings(x []string)メソッドの追加
-
src/pkg/exp/locale/collate/sort_test.go:ExampleCollator_Strings()関数(Collator.Stringsの使用例)- テスト用の
sorter型(Listerインターフェースの実装例) TestSort()関数(Collator.Sortのテスト)
これらの追加により、exp/locale/collate パッケージは、照合キーを直接操作することなく、ロケール固有のソートを直接実行できる高レベルなAPIを提供するようになりました。
コアとなるコードの解説
このコミットの核心は、ユーザーが照合キーの生成と管理という複雑なタスクから解放されるように、ソートロジックを Collator 型の内部にカプセル化した点にあります。
Collator.Sort(x Lister) の動作
Collator.SortメソッドがListerインターフェースを満たすxを引数として受け取ります。- 内部で
c.sorter.init(n)を呼び出し、ソートに必要な内部バッファとキーのスライスを初期化します。 forループでxの各要素 (iからn-1まで) を反復処理します。- 各要素について、
c.sorter.keys[i] = c.Key(c.sorter.buf, x.Bytes(i))を呼び出します。ここでc.KeyはCollatorの既存のメソッドであり、x.Bytes(i)からロケール固有の照合キーを生成し、それをc.sorter.keysスライスに格納します。c.sorter.bufはキー生成時のメモリ割り当てを最適化するためのバッファです。 - すべての照合キーが生成された後、
c.sorter.sort(x)を呼び出します。このsortメソッドは、c.sorter自身をsort.Sort関数に渡し、xをsorterのsrcフィールドに設定します。 sort.Sortはc.sorterのLen,Less,Swapメソッドを呼び出してソートを実行します。- 特に重要なのは
c.sorter.Swap(i, j)メソッドです。このメソッドは、c.sorter.keys内の照合キーを交換するだけでなく、c.src.Swap(i, j)を呼び出すことで、元のデータ (x) の要素も同時に交換します。これにより、照合キーの順序が元のデータの順序に反映されます。
Collator.Strings(x []string) の動作
このメソッドは []string 型に特化した便利なラッパーです。
c.sorter.init(len(x))を呼び出し、内部バッファとキーのスライスを初期化します。forループでxの各文字列sを反復処理します。c.sorter.keys[i] = c.KeyFromString(c.sorter.buf, s)を呼び出し、各文字列から照合キーを生成して格納します。c.sorter.sort(sort.StringSlice(x))を呼び出します。ここでsort.StringSlice(x)は、Go標準ライブラリのsortパッケージが提供する[]stringをsort.Interfaceに適合させるためのアダプターです。このアダプターはswapperインターフェースも満たすため、c.sorter.sortに渡すことができます。
これらの変更により、開発者は collate.New("en").Strings(myStrings) のように、非常に直感的な方法でロケール固有の文字列ソートを実行できるようになりました。
関連リンク
- Go CL 7060051: https://golang.org/cl/7060051 (このコミットに対応するGoの変更リスト)
参考にした情報源リンク
- GoDoc for
golang.org/x/text/collate: https://pkg.go.dev/golang.org/x/text/collate - ActiveState: Go Collation Keys: https://www.activestate.com/blog/go-collation-keys/
- GitHub:
golang/textrepository: https://github.com/golang/text