[インデックス 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/text
repository: https://github.com/golang/text