iOS
App
Objective-C
Swift
JAVA
C#
JavaScript
中文字的筆劃排序
2018/05/02 12:20:37
1
4831
中文字的筆劃排序
簡介 |
介紹中文字如何依照筆劃排序 |
作者 |
陳傑雄 |
中文字的筆劃排序
先前某個專案遇到一個需求:有一個陣列,裡面有一堆中文姓名字串資料,客戶希望這些包含姓名字串的
陣列資料,可以依照特別的中文索引方式排序,像是使用筆劃數、拼音...等等。
花時間研究之後,發現只要在 compare 的時候,選擇特定的 Locale 就好了,從研究 iOS 的案例開始,我們也發現在目前版本的 JAVA、C# 和 JavaScript 也已經支援這種中文排序方式了,
所以特別記錄下來與大家分享。
緣起:在Mac OS X / iOS 上指定中文筆劃排序
如前面所講的,專案需求的原因,才開始研究如何對中文字依筆劃數做索引排序,雖說最後發現只要選擇特定的 Locale 就可以,但是 Apple Inc. 本身的文件中,居然對於有這些 Locale 可以設定卻沒有什麼著墨,顯然地,很多時候光看 Apple 的文件是不夠的。
在 Mac OS X / iOS 中,所有與各種不同國家、語言中使用的不同曆法、日期格式、數字格式相關的資訊,也就是 NSDateFormatter、NSNumberFormatter、NSLocale 這些 class 底下,其實呼叫是 IBM 的 OpenSource 專案 ICU,所以,ICU 支援哪些 Locale,NSLocale 裡頭就可以使用哪些 Locale。
在 ICU 的 Locale 中,我們需要注意的,就是可以在語系(像是 zh)與地區(像是 TW)之後,還可以繼續加上 keyword,keyword 可以是曆法、排序方式、貨幣與數字格式,範例程式碼是指定以筆劃數順序排序的中文語系,就會寫成 zh@collation=stroke。ICU 還支援拼音(pinyin)、Big5 編碼順序(big5han)、GB2312 編碼順序(gb2312)以及部首筆劃順序(unihan)。
由於系統裡頭已經有了一份 ICU library,我們也可以直接呼叫 ICU 的 C 或是 C++ API,做我們在上面做的這件事情。但是在 Mac OS X/iOS 上面想要使用系統內建的 ICU library 還頂麻煩,雖然我們可以讓 linker 直接去連結 libicucore.dylib,但是系統裡頭卻沒有放 ICU 的 header,所以還是要去下載一份 ICU 把 header 挖出來用,另外還要設一些 compiler 參數(詳情可以參考 Lukhnos 去年的這篇 Using OS X’s Built-in ICU Library in Your Own Project)。所幸的是,目前
Cocoa Framework 已經幫我們做好這些事了,
直接呼叫它,寫好 Objective-C 或 Swift 就好了。
這邊我寫了一些小小的範例程式,看看 Swift 和 Objective-C 怎麼對陣列裡的資料完成中文筆劃排序:
Swift
// 定義一個中文字串資料的陣列
var strArray:[String] = ["趙", "錢", "孫", "李", "周", "吳", "鄭", "王", "馮", "陳", "褚", "衛", "蔣", "沈", "韓", "楊"]
// 宣告文化特徵 locale 為 zh_TW
let locale = Locale(identifier: "zh_TW")
// 對陣列做比對和升冪排序
strAry = strAry.sorted(by: { $0.compare($1, locale: locale) == .orderedAscending})
// 將排序後的陣列逐一印出
for str in strAry {
print(str)
}
Objective-C
// 定義一個中文字串資料陣列
NSArray* strAry = @[@"趙", @"錢", @"孫", @"李", @"周", @"吳", @"鄭", @"王", @"馮", @"陳", @"褚", @"衛", @"蔣", @"沈", @"韓", @"楊"];
// 宣告文化特徵 locale 為 zh,並指定以筆劃排序
NSLocale* locale = [[NSLocale alloc] initWithLocaleIdentifier:@"zh@collation=stroke"];
// 對陣列做比對和升冪排序
strAry = [strAry sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [obj1 compare:obj2 options:0 range:NSMakeRange(0, [obj1 length]) locale:locale];
}];
// 將排序後的陣列逐一印出
for (NSString* s in strAry) {
NSLog(@"%@", s);
}
延伸:在其他程式語言中指定中文筆劃排序
接著我們想到在其他程式語言中是否也能以相同的方式,來做到對中文字串資料做筆畫排序呢?
至少我們在實際測試中,JAVA、C#、JavaScript 顯示結果是肯定的,其它的語言留給大家試試看了。
至少我們在實際測試中,JAVA、C#、JavaScript 顯示結果是肯定的,其它的語言留給大家試試看了。
下面是其他程式語言的範例程式碼,供大家參考。
JAVA
public class Asc implements Comparator {
public int compare(Object arg0, Object arg1) {
VLG_ItemMaster m1 = (VLG_ItemMaster)arg0;
VLG_ItemMaster m2 = (VLG_ItemMaster)arg1;
Collator collator = Collator.getInstance(Locale.TRADITIONAL_CHINESE);
return collator.compare(m1.getItemDesc(), m2.getItemDesc());
}
}
C#
using System;
using System.Globalization;
using System.Threading;
public class ArraySort
{
public static void Main(String[] args)
{
// 定義一個中文字串資料陣列
string[] stringArray = { "趙", "錢", "孫", "李", "周", "吳", "鄭", "王", "馮", "陳", "褚", "衛", "蔣"};
// 印出原字串陣列資料
Console.WriteLine( "The original string array:");
PrintIndexAndValues(stringArray);
// 宣告文化特徵 locale 為 "zh-TW"
Thread.CurrentThread.CurrentCulture = new CultureInfo("zh-TW");
// 排序陣列
Array.Sort(stringArray);
// 印出排序後的新字串陣列資料
Console.WriteLine("After sorting for the culture \"zh-TW\":");
PrintIndexAndValues(stringArray);
}
public static void PrintIndexAndValues(string[] myArray)
{
for (int i = myArray.GetLowerBound(0); i <=
myArray.GetUpperBound(0); i++ )
Console.WriteLine("[{0}]: {1}", i, myArray[i]);
Console.WriteLine();
}
}
JavaScript
<html>
<body style="font-size: 9pt">
<script>
var raw = "趙錢孫李周吳鄭王馮陳褚衛蔣";
var ary = [];
for (var i = 0; i < raw.length; i++)
ary.push(raw.substr(i, 1));
document.write("原始順序(BIG5/筆劃)<br />")
document.write(JSON.stringify(ary, null ," "));
document.write("<hr />")
ary.sort();
document.write("內建 sort()<br />")
document.write(JSON.stringify(ary, null ," "));
document.write("<hr />")
ary.sort(function(a,b) { return a.localeCompare(b); });
document.write("localeCompare 排序<br />")
document.write(JSON.stringify(ary, null ," "));
document.write("<hr />")
if (navigator.userAgent.indexOf("Chrome") != -1
|| navigator.userAgent.indexOf("Safari") != -1) {
|| navigator.userAgent.indexOf("Safari") != -1) {
// chrome 和 Safari 瀏覽器需用 "zh_Hant"
ary.sort(function(a,b) { return a.localeCompare(b, "zh-Hant"); });
} else {
// 其他瀏覽器使用 "zh-TW"
ary.sort(function(a,b) { return a.localeCompare(b, "zh-TW"); });
}
document.write("localeCompare zh-TW 排序<br />")
document.write(JSON.stringify(ary, null ," "));
</script>
</body>
</html>