Повторная реализация ToUpper()

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

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


person Colin Pickard    schedule 02.12.2008    source источник


Ответы (6)


  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" и т.п.). Теперь вы можете искать похожее имя с заменой «МАЛЕНЬКИЙ» на «ПРОПИСНОЙ». Если вы его нашли, вы нашли заглавную версию.

person Aaron Digulla    schedule 02.12.2008
comment
4. ПРИБЫЛЬ :) +1 хороший ответ - person leppie; 02.12.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 "χαοσ")      ⇒ "ΧΑΟΣ"
person leppie    schedule 02.12.2008
comment
(строка в верхнем регистре Straße) ⇒ STRAÞE - person hangy; 02.12.2008
comment
Hangy, извините, что не рендерит. Кроме того, мои преобразования не зависят от локальной среды (думаю, я должен был упомянуть об этом ;p). - person leppie; 02.12.2008
comment
А я просто вставил из спецификации R6RS Scheme, может опечатка, проверю тестами. - person leppie; 02.12.2008
comment
Кажется, это правильно. Ребята из Scheme очень педантичны, поверю им на слово :) - person leppie; 02.12.2008
comment
Буква ß в верхнем регистре была добавлена ​​в стандарт Unicode путем обновления некоторых стандартов ISO еще в апреле, поэтому поддержка шрифтов действительно редка. :) Кроме того, Duden еще не принял его в стандартный язык, так что ваш правильный. :) Просто хотел указать еще одну возможность в будущем. - person hangy; 03.12.2008
comment
Спасибо за разъяснения, буду ссылаться на ваш пост :) - person leppie; 03.12.2008

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

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

person Douglas Leeder    schedule 02.12.2008
comment
Уфф. Думаю, именно поэтому правильная библиотека i18n занимает 10 МБ. Сумасшедшие люди. Почему наши предки не могли просто согласиться на красивую простую ЕДИНСТВЕННУЮ систему письма? :П - person Vilx-; 02.12.2008

Я не выиграю бонусные очки, но вот для 7-битного ASCII:

char toupper(char c)
{
    if ((c < 'a') || (c > 'z')) { return c; }
    else { return c & 0xdf; }
}
person e.James    schedule 02.12.2008
comment
Это почти тот же макрос, что и в strings.h. - person Paul Tomblin; 02.12.2008
comment
@Пол Томблин: Хорошо! Я надеялся приблизиться :) - person e.James; 02.12.2008
comment
Как насчет верхних 128 символов? Ты хотел сказать 7-битный? - person leppie; 02.12.2008
comment
Если подумать, если я правильно помню, я думаю, что макрос действительно добавил ('A'-'a'). И да, @leppie, это работало только для ASCII, который по определению является 7-битным. - person Paul Tomblin; 02.12.2008
comment
проверка на (c ‹ 'a') || ( c › 'z') обрабатывает 128..255 (или 0..-127, если указан символ со знаком). Суть в том, что изменяются только 26 символов от «а» до «z». - person e.James; 02.12.2008
comment
eJames: придирка заключалась в том, что ASCII всего 7 бит. Восемь бит всегда равен 0, иначе вы на самом деле не используете ASCII. - person Joachim Sauer; 02.12.2008
comment
Ах хорошо. Справедливо! Я изменю свой ответ. - person e.James; 02.12.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
person hasen    schedule 02.12.2008

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

person Boris Gorelik    schedule 02.12.2008
comment
для этих языков это было бы чрезвычайно просто ... в любом случае арабский и иврит имеют свой собственный набор необходимых им функций для работы со строками. - person hasen; 02.12.2008