2013-06-05 33 views
10

Sıralamak istediğim Arapça bir sözcükler listesi var. Standart Yerleştiriciyi farklı Locales'lerle (İngilizce veya Fransızca gibi ama çok fazla umutsuz) denedim ve kendi RuleBasedCollator'ımı bile oluşturdum ama boşuna. Görünüşe göre, varsayılan sıralama, birçok durumda çalıştığı ancak görünüşte bu şekilde olmayan, unicode değerler sırasına dayanır.Java dilinde Arapça kelimeleri sıralama

Javadocs'un yönergelerini izleyerek, RuleBasedCollator karakterlerin sıralanmasını istediğiniz sırayla belirten bir dize gerektirir. Ben this table den Unicode kodları alarak aşağıdaki dizeyi yarattı:

String arabicLetters = "< \u0623=\uFE83=\uFE84 < \u0628=\uFE8F=\uFE90=\uFE92=\uFE91 < \u062A=\uFE95=\uFE96=\uFE98=\uFE97 < \u062B=\uFE99=\uFE9A=\uFE9C=\uFE9B < \u062C=\uFE9D=\uFE9E=\uFEA0=\uFE9F < \u062D=\uFEA1=\uFEA2=\uFEA4=\uFEA3 < \u062E=\uFEA5=\uFEA6=\uFEA8=\uFEA7 < \u062F=\uFEA9=\uFEAA < \u0630=\uFEAB=\uFEAC < \u0631=\uFEAD=\uFEAE < \u0632=\uFEAF=\uFEB0 < \u0633=\uFEB1=\uFEB2=\uFEB4=\uFEB3 < \u0634=\uFEB5=\uFEB6=\uFEB8=\uFEB7 < \u0635=\uFEB9=\uFEBA=\uFEBC=\uFEBB < \u0636=\uFEBD=\uFEBE=\uFEC0=\uFEBF < \u0637=\uFEC1=\uFEC2=\uFEC4=\uFEC3 < \u0638=\uFEC5=\uFEC6=\uFEC8=\uFEC7 < \u0639=\uFEC9=\uFECA=\uFECC=\uFECB < \u063A=\uFECD=\uFECE=\uFED0=\uFECF < \u0641=\uFED1=\uFED2=\uFED4=\uFED3 < \u0642=\uFED5=\uFED6=\uFED8=\uFED7 < \u0643=\uFED9=\uFEDA=\uFEDC=\uFEDB < \u0644=\uFEDD=\uFEDE=\uFED0=\uFEDF < \u0645=\uFEE1=\uFEE2=\uFEE4=\uFEE3 < \u0646=\uFEE5=\uFEE6=\uFEE8=\uFEE7 < \u0647=\uFEE9=\uFEEA=\uFEEC=\uFEEB < \u0648=\uFEED=\uFEEE < \u064A=\uFEF1=\uFEF2=\uFEF4=\uFEF3 < \u0622=\uFE81=\uFE82 < \u0629=\uFE93=\uFE94 < \u0649=\uFEEF=\uFEF0 < \u0627"; 

Arap harfleri onlar bir kelime olan pozisyona bağlı olarak dört şekillerde olabilir. Bu nedenle, yukarıdaki kural dizisinde yaptığım her harfin 4 formunu eşit hale getirmektir. Sonra onları '<' ile ayıran harflerin sırasını belirtiyorum. Bunu yapmanın doğru yolu olduğunu hayal ediyorum. Ben haftanın günleri ile bir koleksiyon varsa

Şimdi (değil 'alfabetik', haftanın gününe göre bu durumda sıralı):

الأَحَد, الاِثنَين, الثُّلاثاء, الأَربِعاء, الخَميس, الجُمعة,السَّبت 

alıyorum sonuçları en sıralanır değil hepsi:

الأَحَد, الخَميس, الاِثنَين, الثُّلاثاء, الأَربِعاء, السَّبت, الجُمعة 

yanında kelimelerin böyle küçük bir miktar için o kullanışsız kılan bir zaman önemli miktarda alır.

Yanlış bir şey yapıyorum ya da zaten bunu işleyen bir hayat kurtarıcı kitaplık varsa, kimse var mı?

Bunu yazmadan önce biraz googling yaptım ve tek bir sonuç bulamadığım için şaşırdım.

Teşekkürler! koduyla


GÜNCELLEME: Sadece kullanmak, kendi burster tanımlamak gerekmez

public static class TranslatableComparator implements java.util.Comparator<Translatable> { 
     @Override 
     public int compare(Translatable t1, Translatable t2) { 

      String sortingRules = "< \u0623=\uFE83=\uFE84 < \u0628=\uFE8F=\uFE90=\uFE92=\uFE91 < \u062A=\uFE95=\uFE96=\uFE98=\uFE97 < \u062B=\uFE99=\uFE9A=\uFE9C=\uFE9B < \u062C=\uFE9D=\uFE9E=\uFEA0=\uFE9F < \u062D=\uFEA1=\uFEA2=\uFEA4=\uFEA3 < \u062E=\uFEA5=\uFEA6=\uFEA8=\uFEA7 < \u062F=\uFEA9=\uFEAA < \u0630=\uFEAB=\uFEAC < \u0631=\uFEAD=\uFEAE < \u0632=\uFEAF=\uFEB0 < \u0633=\uFEB1=\uFEB2=\uFEB4=\uFEB3 < \u0634=\uFEB5=\uFEB6=\uFEB8=\uFEB7 < \u0635=\uFEB9=\uFEBA=\uFEBC=\uFEBB < \u0636=\uFEBD=\uFEBE=\uFEC0=\uFEBF < \u0637=\uFEC1=\uFEC2=\uFEC4=\uFEC3 < \u0638=\uFEC5=\uFEC6=\uFEC8=\uFEC7 < \u0639=\uFEC9=\uFECA=\uFECC=\uFECB < \u063A=\uFECD=\uFECE=\uFED0=\uFECF < \u0641=\uFED1=\uFED2=\uFED4=\uFED3 < \u0642=\uFED5=\uFED6=\uFED8=\uFED7 < \u0643=\uFED9=\uFEDA=\uFEDC=\uFEDB < \u0644=\uFEDD=\uFEDE=\uFED0=\uFEDF < \u0645=\uFEE1=\uFEE2=\uFEE4=\uFEE3 < \u0646=\uFEE5=\uFEE6=\uFEE8=\uFEE7 < \u0647=\uFEE9=\uFEEA=\uFEEC=\uFEEB < \u0648=\uFEED=\uFEEE < \u064A=\uFEF1=\uFEF2=\uFEF4=\uFEF3 < \u0622=\uFE81=\uFE82 < \u0629=\uFE93=\uFE94 < \u0649=\uFEEF=\uFEF0 < \u0627"; 
      RuleBasedCollator col = null; 
      try { 
       col = new RuleBasedCollator(sortingRules); 
      } catch (ParseException e) { 
       //col = (RuleBasedCollator)RuleBasedCollator.getInstance(Locale.FRENCH); 
      } 

      return col.getCollationKey(t1.getTranslation().getText()).compareTo(col.getCollationKey(t2.getTranslation().getText())); 
     } 
    } 
+1

kod biraz daha lütfen gönderebilir: Gerçekten farklılıklar tanımlanmış ve standart harmanlama olanlar arasında nerede sadece kuralları çıktısını, görmek istiyorsanız

? sadece gerçekte neler olduğunu görebiliriz? – shaunvxc

+0

@shaunvxc, kod ile güncellendi. – Gonan

+0

RuleBasedCollator ile tam olarak aşina değilim, ancak değeri, virgüllerle eşit olmasını istediğiniz karakterleri ayırdığınızda ne olur? Bunun gibi bir şey: " shaunvxc

cevap

5

yerleşik Arapça için biri. Sizin Comparator sonra benziyor bu

public int compare(Translatable t1, Translatable t2) { 
     Collator.getInstance(new Locale("ar")).compare(t1.getTranslation().getText(), t2.getTranslation().getText()); 
} 

(bir harmanlama Collator.getAvailableLocales() sonuçları göz atarak Arapça için kullanılabilir durumda olup olmadığını kontrol edebilirsiniz.) Açıklamalarda belirtildiği gibi

, performans endişe iseniz harmanlama anahtarlarını hesaplamalı, bunları Translatable nesnelerinizde saklamalı ve yerine koymalısınız.

System.out.println((RuleBasedCollator) Collator.getInstance(new Locale("ar"))).getRules(); 
+0

Onarıyorum. Kodda başka bir yerde yanlış bir şeyler yapıyorum. Temel olarak Listeyi bu yöntemle ayırmadan önce değiştiriyordum ve bu yüzden yanlış sonuçlar elde ediyordum. Yanıt olarak, bunun için özel bir Harmanlayıcı kullanmanıza gerek yoktur. Sıralama, karakterlerin Unicode değerlerini alarak çalışır ve alfabetik olarak sıralandıklarından budur. Performans hakkında, aslında her karşılaştırma için bir nesne oluşturduğumu fark etmemiştim. Onu superEB'nin önerdiği şekilde değiştirdim ve şimdi bir saniyeden daha az sürüyor. Teşekkürler! – Gonan

+0

RuleBasedCollator yaklaşımını denemeden önce yaptığım şey buydu ve temelde bunu yapmanın yolu olduğu için, bunu yanıt olarak işaretlerim. – Gonan