Reply to
Re: Chuyển tiếng Việt có dấu sang không dấu?
(
NBThanh)
Cám ơn các bạn. Trong C# có sẵn hàm "normalize" chuỗi unicode nên dễ hơn Delphi.
Đây là hàm "thủ công" (tìm và thay) tôi viết trên Delphi, chia sẻ cho những bạn có nhu cầu sử dụng:
function ManipulateNormalizeUnicode2Byte(AString: WideString): WideString;
const
{ LowerASet: set of WideChar = ['á', 'à', 'ả', 'ã', 'ạ',
'â', 'ấ', 'ầ', 'ẩ', 'ẫ', 'ậ', 'ă', 'ắ', 'ằ', 'ẳ', 'ẵ', 'ặ'];
UpperASet: set of WideChar = ['Á', 'À', 'Ả', 'Ã', 'Ạ',
'Â', 'Ấ', 'Ầ', 'Ẩ', 'Ẫ', 'Ậ', 'Ă', 'Ắ', 'Ằ', 'Ẳ', 'Ẵ', 'Ặ'];
LowerESet: set of WideChar = ['é', 'è', 'ẻ', 'ẽ', 'ẹ',
'ê', 'ế', 'ề', 'ể', 'ễ', 'ệ'];
UpperESet: set of WideChar = ['É', 'È', 'Ẻ', 'Ẽ', 'Ẹ',
'Ê', 'Ế', 'Ề', 'Ể', 'Ễ', 'Ệ'];
LowerISet: set of WideChar = ['í', 'ì', 'ỉ', 'ĩ', 'ị'];
UpperISet: set of WideChar = ['Í', 'Ì', 'Ỉ', 'Ĩ', 'Ị'];
LowerOSet: set of WideChar = ['ó', 'ò', 'ỏ', 'õ', 'ọ',
'ô', 'ố', 'ồ', 'ổ', 'ỗ', 'ộ', 'ơ', 'ớ', 'ờ', 'ở', 'ỡ', 'ợ'];
UpperOSet: set of WideChar = ['Ó', 'Ò', 'Ỏ', 'Õ', 'Ọ',
'Ô', 'Ố', 'Ồ', 'Ổ', 'Ỗ', 'Ộ', 'Ơ', 'Ớ', 'Ờ', 'Ở', 'Ỡ', 'Ợ'];
LowerUSet: set of WideChar = ['ú', 'ù', 'ủ', 'ũ', 'ụ',
'ư', 'ứ', 'ừ', 'ử', 'ữ', 'ự'];
UpperUSet: set of WideChar = ['Ú', 'Ù', 'Ủ', 'Ũ', 'Ụ',
'Ư', 'Ứ', 'Ừ', 'Ử', 'Ữ', 'Ự'];
LowerYSet: set of WideChar = ['ý', 'ỳ', 'ỷ', 'ỹ', 'ỵ'];
UpperYSet: set of WideChar = ['Ý', 'Ỳ', 'Ỷ', 'Ỹ', 'Ỵ'];
}
LowerASet: array[0..16] of Word = ($00E1, $00E0, $1EA3, $00E3, $1EA1,
$00E2, $1EA5, $1EA7, $1EA9, $1EAB, $1EAD,
$0103, $1EAF, $1EB1, $1EB3, $1EB5, $1EB7);
UpperASet: array[0..16] of Word = ($00C1, $00C0, $1EA2, $00C3, $1EA0,
$00C2, $1EA4, $1EA6, $1EA8, $1EAA, $1EAC,
$0102, $1EAE, $1EB0, $1EB2, $1EB4, $1EB6);
LowerESet: array[0..10] of Word = ($00E9, $00E8, $1EBB, $1EBD, $1EB9,
$00EA, $1EBF, $1EC1, $1EC3, $1EC5, $1EC7);
UpperESet: array[0..10] of Word = ($00C9, $00C8, $1EBA, $1EBC, $1EB8,
$00CA, $1EBE, $1EC0, $1EC2, $1EC4, $1EC6);
LowerISet: array[0..4] of Word = ($00ED, $00EC, $1EC9, $0129, $1ECB);
UpperISet: array[0..4] of Word = ($00CD, $00CC, $1EC8, $0128, $1ECA);
LowerOSet: array[0..16] of Word = ($00F3, $00F2, $1ECF, $00F5, $1ECD,
$00F4, $1ED1, $1ED3, $1ED5, $1ED7, $1ED9,
$01A1, $1EDB, $1EDD, $1EDF, $1EE1, $1EE3);
UpperOSet: array[0..16] of Word = ($00D3, $00D2, $1ECE, $00D5, $1ECC,
$00D4, $1ED0, $1ED2, $1ED4, $1ED6, $1ED8,
$01A0, $1EDA, $1EDC, $1EDE, $1EE0, $1EE2);
LowerUSet: array[0..10] of Word = ($00FA, $00F9, $1EE7, $0169, $1EE5,
$01B0, $1EE9, $1EEB, $1EED, $1EEF, $1EF1);
UpperUSet: array[0..10] of Word = ($00DA, $00D9, $1EE6, $0168, $1EE4,
$01AF, $1EE8, $1EEA, $1EEC, $1EEE, $1EF0);
LowerYSet: array[0..4] of Word = ($00FD, $1EF3, $1EF7, $1EF9, $1EF5);
UpperYSet: array[0..4] of Word = ($00DD, $1EF2, $1EF6, $1EF8, $1EF4);
LowerDSet: array[0..0] of Word = ($0111);
UpperDSet: array[0..0] of Word = ($0110);
//
function Check(CharCode: Word; Values: array of Word): Boolean;
// hàm trả về True nếu CharCode có trong mảng ký tự có dấu của tiếng Việt
var
i: Byte;
begin
for i := 0 to High(Values) do
begin
Result := Values[i] = CharCode;
if Result then Break;
end;
end;
//
var
i: Integer;
CharCode: Word;
begin
Result := AString;
for i := 1 to Length(Result) do
begin
CharCode := Word(Result[i]);
// dùng if..else liên tục để thoát vòng lặp và nhảy đến ký tự kế tiếp
// ngay khi xử lý xong 1 ký tự, tránh trường hợp so sánh nhiều lần
// ở nhiều mảng ký tự khác nhau
if Check(CharCode, LowerASet) then
Result[i] := 'a'
else if Check(CharCode, UpperASet) then
Result[i] := 'A'
else if Check(CharCode, LowerESet) then
Result[i] := 'e'
else if Check(CharCode, UpperESet) then
Result[i] := 'E'
else if Check(CharCode, LowerISet) then
Result[i] := 'i'
else if Check(CharCode, UpperISet) then
Result[i] := 'I'
else if Check(CharCode, LowerOSet) then
Result[i] := 'o'
else if Check(CharCode, UpperOSet) then
Result[i] := 'O'
else if Check(CharCode, LowerUSet) then
Result[i] := 'u'
else if Check(CharCode, UpperUSet) then
Result[i] := 'U'
else if Check(CharCode, LowerYSet) then
Result[i] := 'y'
else if Check(CharCode, UpperYSet) then
Result[i] := 'Y'
else if Check(CharCode, LowerDSet) then
Result[i] := 'd'
else if Check(CharCode, UpperDSet) then
Result[i] := 'D';
end;
end;
Tôi làm chương trình trên nền WinForm, kiểm thử với 100.000 truy vấn tìm kiếm, mỗi truy vấn trung bình là một chuỗi unicode 10 ~ 13 ký tự, kết quả khi gọi hàm trên thì thời gian tiêu tốn hơn khoảng 110% so với không gọi hàm. Như vậy có lẽ cũng tạm ổn :)
Nếu bạn nào còn cách khác tối ưu hơn vui lòng trình bày để mọi người cùng sử dụng, cám ơn bạn.
___________________________
sorry for my bad En...
This post has been edited 2 time(s).
Last edited by freeman on 19:12 17-12-2009.
This post has been viewed
3,050
time(s).
0 direct repli(es)
and
0 indirect repli(es).