Переопределение ToUpper () - PullRequest
3 голосов
/ 02 декабря 2008

Как бы вы написали ToUpper (), если бы его не было? Бонусные баллы для i18n и L10n

Любопытство, вызванное этим: http://thedailywtf.com/Articles/The-Long-Way-toUpper.aspx

Ответы [ 6 ]

8 голосов
/ 02 декабря 2008
  1. Я загружаю таблицы Unicode
  2. импортирую таблицы в базу данных
  3. Я пишу метод upper ().

Вот пример реализации;)

public static String upper(String s) {
    if (s == null) {
        return null;
    }

    final int N = s.length(); // Mind the optimization!
    PreparedStatement stmtName = null;
    PreparedStatement stmtSmall = null;
    ResultSet rsName = null;
    ResultSet rsSmall = null;
    StringBuilder buffer = new StringBuilder (N); // Much faster than StringBuffer!
    try {
        conn = DBFactory.getConnection();
        stmtName = conn.prepareStatement("select name from unicode.chart where codepoint = ?");
        // TODO Optimization: Maybe move this in the if() so we don't create this
        // unless there are uppercase characters in the string.
        stmtSmall = conn.prepareStatement("select codepoint from unicode.chart where name = ?");
        for (int i=0; i<N; i++) {
            int c = s.charAt(i);
            stmtName.setInt(1, c);
            rsName = stmtName.execute();
            if (rsName.next()) {
                String name = rsName.getString(1);
                if (name.contains(" SMALL ")) {
                    name = name.replaceAll(" SMALL ", " CAPITAL ");

                    stmtSmall.setString(1, name);
                    rsSmall = stmtSmall.execute();
                    if (rsSmall.next()) {
                        c = rsSmall.getInt(1);
                    }

                    rsSmall = DBUtil.close(rsSmall);
                }
            }
            rsName = DBUtil.close(rsName);
        }
    }
    finally {
        // Always clean up
        rsSmall = DBUtil.close(rsSmall);
        rsName = DBUtil.close(rsName);
        stmtSmall = DBUtil.close(stmtSmall);
        stmtName = DBUtil.close(stmtName);
    }

    // TODO Optimization: Maybe read the table once into RAM at the start
    // Would waste a lot of memory, though :/
    return buffer.toString();
}

;)

Примечание. Диаграммы Unicode, которые вы можете найти на unicode.org , содержат имя символа / кодовой точки. Эта строка будет содержать «SMALL» для символов в верхнем регистре (обратите внимание на пробелы, или она может совпадать с «SMALLER» и т. П.). Теперь вы можете искать похожее имя с «МАЛЫМ», замененным «КАПИТАЛОМ». Если вы найдете его, вы нашли его версию.

7 голосов
/ 02 декабря 2008

Я не думаю, что SO может обрабатывать размер таблиц Unicode в одной публикации:)

К сожалению, это не так просто, как просто char.ToUpper () для каждого символа.

Пример:

(string-upcase "Straße")    ⇒ "STRASSE"
(string-downcase "Straße")  ⇒ "straße"
(string-upcase "ΧΑΟΣ")      ⇒ "ΧΑΟΣ"
(string-downcase "ΧΑΟΣ")    ⇒ "χαος"
(string-downcase "ΧΑΟΣΣ")   ⇒ "χαοσς"
(string-downcase "ΧΑΟΣ Σ")  ⇒ "χαος σ"
(string-upcase "χαος")      ⇒ "ΧΑΟΣ"
(string-upcase "χαοσ")      ⇒ "ΧΑΟΣ"
5 голосов
/ 02 декабря 2008

Статической таблицы не будет достаточно, потому что вам нужно знать язык, прежде чем вы знаете правильные преобразования.

например. На турецком i необходимо перейти на İ (U + 0130), тогда как на любом другом языке необходимо перейти на I (U + 0049). И i - это тот же символ U + 0069.

1 голос
/ 02 декабря 2008

Я не выиграю бонусные баллы, но здесь это для 7-битной ASCII:

char toupper(char c)
{
    if ((c < 'a') || (c > 'z')) { return c; }
    else { return c & 0xdf; }
}
0 голосов
/ 02 декабря 2008

Позвольте мне предложить еще больше бонусных баллов за такие языки, как иврит, арабский, грузинский и другие, которые просто не имеют заглавных (заглавных) букв. : -)

0 голосов
/ 02 декабря 2008

в питоне ..

touppe_map = { massive dictionary to handle all cases in all languages }
def to_upper( c ):
   return toupper_map.get( c, c )

или, если вы хотите сделать «неправильный путь»

def to_upper( c ):
  for k,v in toupper_map.items():
     if k == c: return v
  return c
...