C#:サロゲートペアを考慮した文字の列挙に foreach を使えるようにする †
C#で文字列を1文字ずつ処理する場合、何も考えなければ次のような感じで書くと思います。
1
2
3
4
5
|
-
-
!
| string text = "あいうえお";
foreach (var c in text)
{
}
|
しかしこれだと文字列にサロゲートペア(4バイトで表されるUnicode文字)が含まれている場合に正常な処理が行えません。
なのでサロゲートペアを考慮した列挙を行う場合は System.Globalization.StringInfo
クラスの静的メソッド GetTextElementEnumerator
を使って取得した TextElementEnumerator
オブジェクトを用いて処理することになります。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
-
|
|
-
-
!
!
|
-
-
!
!
| string text = "あいうえお";
var e = StringInfo.GetTextElementEnumerator(text);
while (e.MoveNext())
{
string s = e.GetTextElement();
if (s.Length == 1)
{
char c = s[0];
}
else
{
}
}
|
しかし私はこのメソッドを使うたびに思うのです。
「IEnumerator
じゃなくて IEnumerable
なオブジェクトを返してくれよ!」と。
なぜなら、そうすれば foreach
なり各種拡張メソッドなりが利用できるからです。
そういうわけでこんなクラスを作りました。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
-
-
|
|
!
-
-
|
|
|
!
-
|
!
|
-
|
|
!
|
-
|
|
|
!
-
|
!
|
|
|
|
-
|
!
|
|
!
!
| using System;
using System.Collections;
using System.Globalization;
namespace ruche.util
{
public class TextElementEnumerable : IEnumerable
{
public TextElementEnumerable(string source)
{
this.Source = source;
}
public string Source { get; private set; }
public TextElementEnumerator GetEnumerator()
{
return StringInfo.GetTextElementEnumerator(this.Source);
}
#region IEnumerable の明示的実装
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
#endregion
}
}
|
このクラスを使えば次のように記述できます。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
-
|
-
-
!
!
|
-
-
!
!
| string text = "あいうえお";
foreach (string s in new TextElementEnumerable(text))
{
if (s.Length == 1)
{
char c = s[0];
}
else
{
}
}
|
すっきり!
Category: [
プログラミング][
C#] - 2013-03-14 05:07:34