Sắp xếp mảng - trật tự Alphabet và ký tự non ainsi

798 views
Skip to first unread message

sacroyant

unread,
Feb 15, 2008, 2:38:55 PM2/15/08
to PHPVietnam
Giả sử chúng ta có 1 mảng như sau :

$myArray=array(
'Alfred' ,
'Robert' ,
'Deepak' ,
'Đường' ,
'Ánh' ,
'Jaqueline'
);

Làm thế nào để sắp xếp lại mảng trên theo đúng trật tự alphabet ? Mọi
hàm hỗ trợ sorting trong PHP đều không đánh giá đúng các mẫu tự chữ
cái Tiếng Việt như 'Đường' và 'Ánh'.

Xin các bác cho em 1 vài chỉ dẫn.

An Vu

unread,
Feb 15, 2008, 6:41:50 PM2/15/08
to phpvi...@googlegroups.com
Tự viết lấy 1 hàm sort riêng.

P/S: Về vấn đề mysql không sort đúng tiếng Việt mà bác đã gửi bên ddth.com, có thể dùng 1 cột giả ánh xạ các kí tự tiếng Việt thành không dấu như sau:

Đ => Dz (z hoặc kí tự gì cũng đc)
...

Khi đó chỉ việc sort trên cột giả này là được

Sacroyant Nguyen

unread,
Feb 16, 2008, 3:16:27 AM2/16/08
to phpvi...@googlegroups.com
Hay, thông minh thật. Thì ra là dùng một cột giả ! Vậy mà em không nghĩ ra được. Cảm ơn bác nhiều lắm.

--
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-------------------------------------------------------------------

Sacroyant Nguyen

unread,
Feb 16, 2008, 4:26:13 AM2/16/08
to phpvi...@googlegroups.com
Em dùng 2 mảng thế này có đầy đủ chưa nhỉ các bác ?

$vichar=array(0,1,2,3,4,5,6,7,8,9,'a','A','ă','Ă','â','Â','b','B','c','C','d','D','đ','Đ','e','E','ê','Ê','f','F','g','G','h','H','i','I','j','J','k','K','l','L','m','M','n','N','o','O','ô','Ô','ơ','Ơ','p','P','q','Q','r','R','s','S','t','T','u','U','ư','Ư','v','V','w','W','x','X','y','Y','z','Z');
$rechar=array(0,1,2,3,4,5,6,7,8,9,'a00','a01','a10','a11','a20','a21','b00','b01','c00','c01','d00','d01','d10','d11','e00','e01','e10','e11','f00','f01','g00','g01','h00','h01','i00','i01','j00','j01','k00','k01','l00','l01','m00','m01','n00','n01','o00','o01','o10','o11','o20','o21','p00','p01','q00','q01','r00','r01','s00','s01','t00','t01','u00','u01','u10','u11','v00','v01','w00','w01','x00','x01','y00','y01','z00','z01');


2008/2/16 Sacroyant Nguyen <sacr...@gmail.com>:

Hay, thông minh thật. Thì ra là dùng một cột giả ! Vậy mà em không nghĩ ra được. Cảm ơn bác nhiều lắm.

--
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-------------------------------------------------------------------



--
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-------------------------------------------------------------------

btnguyen2k

unread,
Feb 16, 2008, 5:31:11 AM2/16/08
to PHPVietnam
> P/S: Về vấn đề mysql không sort đúng tiếng Việt mà bác đã gửi bên
ddth.com,
> có thể dùng 1 cột giả ánh xạ các kí tự tiếng Việt thành không dấu
như sau:
>
> Đ => Dz (z hoặc kí tự gì cũng đc)
> ...
>
> Khi đó chỉ việc sort trên cột giả này là được
Cách này có khá nhiều nhược điểm:
- Làm dữ liệu phình lên gấp 2-3 lần. Giả sử cột gốc dài 127 ký tự, vậy
cột giả sẽ có thể vượt quá ngưỡng 255 ký tự.
- Mỗi lần update/insert vào cột chính thì phải đồng thời update ở cột
giả
- Lượng ký tự ần làm giả là khá lớn nếu muốn bao quát hết nhiều trường
hợp

Có lẽ là nên tìm cách khác ổn hơn.

On Feb 16, 6:41 am, "An Vu" <a...@toan2.com> wrote:
> Tự viết lấy 1 hàm sort riêng.
>
> P/S: Về vấn đề mysql không sort đúng tiếng Việt mà bác đã gửi bên ddth.com,
> có thể dùng 1 cột giả ánh xạ các kí tự tiếng Việt thành không dấu như sau:
>
> Đ => Dz (z hoặc kí tự gì cũng đc)
> ...
>
> Khi đó chỉ việc sort trên cột giả này là được
>
> On 2/16/08, sacroyant <sacroy...@gmail.com> wrote:
>
>
>
>
>
> > Giả sử chúng ta có 1 mảng như sau :
>
> > $myArray=array(
> > 'Alfred' ,
> > 'Robert' ,
> > 'Deepak' ,
> > 'Đường' ,
> > 'Ánh' ,
> > 'Jaqueline'
> > );
>
> > Làm thế nào để sắp xếp lại mảng trên theo đúng trật tự alphabet ? Mọi
> > hàm hỗ trợ sorting trong PHP đều không đánh giá đúng các mẫu tự chữ
> > cái Tiếng Việt như 'Đường' và 'Ánh'.
>
> > Xin các bác cho em 1 vài chỉ dẫn.
>
> --
> An Vũhttp://www.symfony.vn

btnguyen2k

unread,
Feb 16, 2008, 5:32:07 AM2/16/08
to PHPVietnam
Còn riêng sort tiếng Việt trong PHP thì tôi đang viết 1 class hỗ trợ,
chắc hết cuối tuần này là có thể xài được :-)

Sacroyant Nguyen

unread,
Feb 16, 2008, 6:28:10 AM2/16/08
to phpvi...@googlegroups.com
Em đã giải quyết xong, mà không cần tác động gì vào database. Khi lấy dữ liệu ra thì trút vào một số mảng tạm, thực hiện sắp xếp trên các mảng này rồi output. Thấy khá ổn và chính xác.

Các bác xem thử nè

--
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-------------------------------------------------------------------

btnguyen2k

unread,
Feb 16, 2008, 6:29:55 AM2/16/08
to PHPVietnam
Lỡ nhiều record quá làm sao mà lấy hết lên memory rồi sort?

On Feb 16, 6:28 pm, "Sacroyant Nguyen" <sacroy...@gmail.com> wrote:
> Em đã giải quyết xong, mà không cần tác động gì vào database. Khi lấy dữ
> liệu ra thì trút vào một số mảng tạm, thực hiện sắp xếp trên các mảng này
> rồi output. Thấy khá ổn và chính xác.
>
> Các bác xem thử nè
> <http://thuvienvl.uni.cc/?action=display&lid=XEMYq37NSztervvO_NS8yjDPE...>
>
> --
> ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
> -------------------------------------------------------------------

sacroyant

unread,
Feb 16, 2008, 6:33:20 AM2/16/08
to PHPVietnam
Cũng biết là chưa tối ưu, nhưng tạm thời dữ liệu cũng ít nên không
quan trọng lắm về vấn đề memory.

Anh Thành viết xong cái class đó thì share cho em 1 bản nhé.

web20vn.com

unread,
Feb 16, 2008, 10:35:12 AM2/16/08
to PHPVietnam
Tạm thời chỉ có cách đó là ổn, thường thì dữ liệu lúc nào lấy ra cũng
có limit nên không tốn memory là bao so với các ngôn ngữ khác như
China, Korea, Japan

An Vu

unread,
Feb 16, 2008, 8:48:54 PM2/16/08
to phpvi...@googlegroups.com
Các kí tự tiếng Việt có dấu có kích thước từ 2-3 bytes nên ánh xạ như vậy không làm cột giả quá giới hạn. Trong khi ánh xạ, chỉ chọn những kí tự nào không đúng thứ tự, chứ không cần phải tất cả các kí tự tiếng Việt

btnguyen2k

unread,
Feb 17, 2008, 3:26:30 AM2/17/08
to PHPVietnam
> Các kí tự tiếng Việt có dấu có kích thước từ 2-3 bytes nên ánh xạ
như vậy
> không làm cột giả quá giới hạn. Trong khi ánh xạ, chỉ chọn những
kí tự nào
> không đúng thứ tự, chứ không cần phải tất cả các kí tự tiếng Việt
Ta đang nói tới vấn đề sort trong db cơ mà. Ví dụ trong DB có 1 column
lưu tiếng Việt (là colName chẳng hạn), ta làm 1 cột giả để "normalize"
các ký tự tiếng Việt thành ký tự ASCII để lưu trong 1 column "giả" để
khi sort với câu lệnh SQL ta sẽ sort trên column này.
Ví dụ với ta tạo column colNameNorm với qui tắc ánh xạ như sau:
a --> a00
ă --> a10
â --> a20
à --> a01

Tức là 1 chữ cái sẽ đi kèm với nó 2 con số, con số đầu tiên để đánh
dấu qui tắc a ă â (u ư, o, ơ, ô...), con số thứ 2 để đánh thanh điệu
(1 = huyền, 2 = hỏi, v...)

Giả sử với chữ Nguyễn ta sẽ phải normalize ra như sau
N00g00u00y00e13n00 (giả sử ễ -> e13)
Thì lúc sort với SQL, ta chỉ cần ORDER BY colNameNorm là xong.

Nhưng như vậy thì dữ liệu dài ra gấp 3 rồi đó (sẽ là 4 lần vì cột
colName là 1 lần, colNameNorm thêm 3 lần nữa là 4!)
(Lưu ý: ta có thể có cách normalize mà chỉ phình lên gấp 2 lần, nhưng
ở đây ta không quan trọng là 2-3 lần mà ở đây chỉ demo ván đề "phình
lên khá nhiều").

Ta không thể ánh xạ "Nguyễn" thành Nguye13n được vì chỉ nếu ánh xạ như
thế thì không đảm bản được mỗi ký tự có độ rộng như nhau, ta sẽ không
so sánh được vì lơ có so sánh, ta phải so sánh e13 với n00 chẳng hạn
(mặc dù rõ ràng n không thể có dấu thanh gì cả), chứ còn so sánh e13
với ngh là trật rồi! Đó là chưa kể dùng các hàm SQL để tính độ dài của
chuỗi nữa (nếu mọi ký tự đều ánh xạ cố định ra 2 hoặc 3 ký tự thì tính
độ dài của chuỗi rõ ràng là dễ dàng).


Và bản thân câu:
> Các kí tự tiếng Việt có dấu có kích thước từ 2-3 bytes...
Cũng không hoàn toàn chính xác vì 2 lý do:
- Phải xem xét với encoding nào? UTF-8 chăng?
- 2-3 bytes là đơn vị lưu trữ trên đĩa, chứ còn DB thì đơn vị lưu trữ
của char column là ký tự, không phải là byte. char(10) không tương ứng
với 10 byte mà là 10 char. Ở đây column là char(10) nên nếu minh lưu
không đủ 10 ký tự thì db sẽ pad thêm space cho đủ 10 ký tự. Tuy nhiên,
không gian lưu trữ có thể thay đổi vì mỗi ký tự có thể là 2-3 bytes
nếu encoding của column là utf-8.

On Feb 17, 8:48 am, "An Vu" <a...@toan2.com> wrote:
> Các kí tự tiếng Việt có dấu có kích thước từ 2-3 bytes nên ánh xạ như vậy
> không làm cột giả quá giới hạn. Trong khi ánh xạ, chỉ chọn những kí tự nào
> không đúng thứ tự, chứ không cần phải tất cả các kí tự tiếng Việt
>
> On 2/16/08, web20vn.com <lekhac...@gmail.com> wrote:
>
>
>
> > Tạm thời chỉ có cách đó là ổn, thường thì dữ liệu lúc nào lấy ra cũng
> > có limit nên không tốn memory là bao so với các ngôn ngữ khác như
> > China, Korea, Japan
>
> --
> An Vũhttp://www.symfony.vn

Sacroyant Nguyen

unread,
Feb 17, 2008, 4:16:42 AM2/17/08
to phpvi...@googlegroups.com
On Feb 17, 8:48 am, "An Vu" <a...@toan2.com> wrote:
 Các kí tự tiếng Việt có dấu có kích thước từ 2-3 bytes nên ánh xạ như vậy
 không làm cột giả quá giới hạn. Trong khi ánh xạ, chỉ chọn những kí tự nào
 không đúng thứ tự, chứ không cần phải tất cả các kí tự tiếng Việt

Nếu ánh xạ thì phải ánh xạ hết mới chính xác bác ạ. Mới đầu em chỉ làm với các nguyên âm có dấu và phụ âm "Đ", thì gặp trường hợp bị sai.

Một kinh nghiệm khác mà em có được là các ký tự đặc biệc cũng làm ảnh hưởng đến sự sắp xếp. Khi ánh xạ cần loại bỏ chúng đi. Ví dụ 2  mẩu tin chứa tựa bài viết trong trường Title như sau :
  1. Nghe em hát đêm buồn.
  2. Nghe "Khúc nhạc chiều"

Nếu không bỏ các nháy kép thì record 2 sẽ được đặt trên record 1, mà điều này không được natural lắm, vì "K" phải đứng sau  "e" trong trật tự alphabet.


--
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-------------------------------------------------------------------
Reply all
Reply to author
Forward
0 new messages