2012-05-16 38 views
2

我有一個使用g_ascii_strcasecmp函數排序的單詞列表。我需要在java中處理這個列表。 java中的等價排序功能是什麼?爲了實現二進制搜索,我需要一個正確的比較函數。到目前爲止,我有下面的功能,但它並不總是產生正確的結果。g_ascii_strcasecmp在java中相當於

public int compareStrings(String str) { 
    Collator collator = Collator.getInstance();//TODO: implement locale? 
    return collator.compare(this.wordString, str); 
} 

UPDATE。列表示例:「T,t,Taiai Chuan,Tother,T,T骨,丁骨牛排,丁字路口,塔巴斯科,塔巴薩蘭,虎斑」。

回答

0

我決定分享我想出了方法:

/** 
    * Compares two strings, ignoring the case of ASCII characters. It treats 
    * non-ASCII characters taking in account case differences. This is an 
    * attempt to mimic glib's string utility function 
    * <a href="http://developer.gnome.org/glib/2.28/glib-String-Utility-Functions.html#g-ascii-strcasecmp">g_ascii_strcasecmp()</a>. 
    * 
    * This is a slightly modified version of java.lang.String.CASE_INSENSITIVE_ORDER.compare(String s1, String s2) method. 
    * 
    * @param str1 string to compare with str2 
    * @param str2 string to compare with str1 
    * @return  0 if the strings match, a negative value if str1 < str2, or a positive value if str1 > str2 
    */ 
    private static int compareToIgnoreCaseASCIIOnly(String str1, String str2) { 
     int n1 = str1.length(); 
     int n2 = str2.length(); 
     int min = Math.min(n1, n2); 
     for (int i = 0; i < min; i++) { 
      char c1 = str1.charAt(i); 
      char c2 = str2.charAt(i); 
      if (c1 != c2) { 
       if ((int) c1 > 127 || (int) c2 > 127) { //if non-ASCII char 
        return c1 - c2; 
       } else { 
        c1 = Character.toUpperCase(c1); 
        c2 = Character.toUpperCase(c2); 
        if(c1 != c2) { 
         c1 = Character.toLowerCase(c1); 
         c2 = Character.toLowerCase(c2); 
         if(c1 != c2) { 
          return c1 - c2; 
         } 
        } 
       } 
      } 
     } 
     return n1 - n2; 
    } 
1

我不會使用Collator,因爲您無法控制字符串的比較方式,因此無法控制它的Javadoc。您可以選擇語言環境,但該語言環境如何告知Collator如何比較字符串不在您的手中。

如果您知道,在你的字符串中的字符都是ASCII字符,那麼我只使用String.compareTo()方法,它的字典順序基於Unicode字符值。如果字符串中的所有字符都是ASCII字符,則它們的Unicode字符值將是它們的ASCII值,因此按照字典順序對其unicode值進行排序將與按字典順序對其ASCII值進行排序相同,這似乎是g_ascii_stcasecmp所做的。如果您需要不區分大小寫,則可以使用String.compareToIgnoreCase()


正如我在評論中指出的,我認爲你需要編寫自己的比較函數。您需要遍歷字符串中的字符,跳過不在ASCII範圍內的字符。所以這樣的事情,這是一個簡單的,愚蠢的實現,需要加強了覆蓋角落情況下,我想象g_ascii_strcasecmp作用:

public int compareStrings(String str) { 
    List<Character> myAsciiChars = onlyAsciiChars(this.wordString); 
    List<Character> theirAsciiChars = onlyAsciiChars(str); 

    if (myAsciiChars.size() > theirAsciiChars.size()) { 
     return 1; 
    } 
    else if (myAsciiChars.size() < theirAsciiChars.size()) { 
     return -1; 
    } 

    for (int i=0; i < myAsciiChars.size(); i++) { 
     if (myAsciiChars.get(i) > theirAsciiChars.get(i)) { 
      return 1; 
     } 
     else if (myAsciiChars.get(i) < theirAsciiChars.get(i)) { 
      return -1; 
     } 
    } 

    return 0; 
} 

private final static char MAX_ASCII_VALUE = 127; // (Or 255 if using extended ASCII) 

private List<Character> onlyAsciiChars(String s) { 
    List<Character> asciiChars = new ArrayList<>(); 
    for (char c : s.toCharArray()) { 
     if (c <= MAX_ASCII_VALUE) { 
      asciiChars.add(c); 
     } 
    } 
    return asciiChars; 
} 
+0

我知道那裏有非ASCII字符。原始編碼是UTF-8,任何可能的字符都可以在那裏,如ò,ø,æ,î,ю,ж,ё。 – bancer

+0

然後這將不起作用,因爲根據您的鏈接,執行比較時,'g_ascii_strcasecmp'忽略非ASCII字符。 'String.compareTo/compareToIgnoreCase'不會。我認爲你將不得不編寫你自己的比較函數。 – QuantumMechanic

+0

非常感謝您的幫助。我認爲在'g_ascii_strcasecmp'中「處理所有非ASCII字節,就好像它們不是字母」,並不意味着非ASCII字符被忽略,而是被視爲字節(或類似字符)。我想我已經想出了該怎麼做。 – bancer