Преобразование строки верхнего регистра в регистр заголовка в Objective-C

Я создал следующий метод, который начинается с использования встроенного метода convertStringToTitleCase в NSString, но на самом деле он просто заглавными буквами первой буквы каждого слова. Я вижу, что в.NET есть метод для TextInfo.ToTitleCase, который пытается сделать то, что я хотел бы сделать с Objective-C, но также терпит неудачу.

http://msdn.microsoft.com/en-us/library/system.globalization.textinfo.totitlecase.aspx

Метод, который я написал, чтобы начать ниже. Как бы вы справились с правильной регистрацией строки в верхнем регистре? Будет ли база данных слов, чтобы преобразовать все прописные / строчные справки?

- (NSString *)convertStringToTitleCase:(NSString *)str {
    NSMutableString *convertedStr = [NSMutableString stringWithString:[str capitalizedString]];

    NSRange range = NSMakeRange(0, convertedStr.length);

    // a list of words to always make lowercase could be placed here
    [convertedStr replaceOccurrencesOfString:@" De " 
                                  withString:@" de " 
                                     options:NSLiteralSearch 
                                       range:range];

    // a list of words to always make uppercase could be placed here
    [convertedStr replaceOccurrencesOfString:@" Tv " 
                                  withString:@" TV " 
                                     options:NSLiteralSearch 
                                       range:range];

    return convertedStr;
}

3 ответа

Решение

Как отмечалось в комментариях, метод.NET, на который вы ссылаетесь, не делает "правильный" регистр заголовка (то есть, следуйте списку исключительных слов, которые следует оставить либо заглавными, либо строчными), поэтому -[NSString capitalizedString] так же, как вы получите. Если вы хотите слова исключения, вам придется написать свой собственный метод (или найти кого-то еще, кто сделал, как поиск в Google для NSString "title case" может быть).

Насколько "правильной" будет ваша заглавная буква, зависит от того, сколько исключительных слов вы готовы к ней добавить. Какую часть английского языка вы хотите поддержать? А как насчет других языков? Это также будет зависеть от того, насколько далеко вы продвинетесь в анализе границ слов - вы можете захотеть, чтобы "ТВ" оставался заглавными, независимо от того, находится ли он в кавычках, в конце предложения и т. Д., Но вы, вероятно, тоже не Я не хочу, чтобы "ты" вышел "Ты".

Если вы хотите обрабатывать слова исключений, ваш план многократного запуска replaceOccurrencesOfString... будет медленнее, чем больше слов исключения у вас есть. (Кроме того, использование пробелов в строках поиска / замены означает, что вы не учитываете другие границы слов, которые вам могут понадобиться.)

Это может быть полезно рассмотреть NSRegularExpression, поскольку регулярные выражения уже имеют достаточно четкие представления о границах падежей и слов. Если это не работает для вас, использование сканера для считывания входной строки при создании преобразованной выходной строки будет более эффективным, чем выполнение нескольких операций поиска / замены.

Хорошая однострочная (не общее решение, вероятно, очень неэффективное на огромных строках):

[[str lowercaseString] capitalizedString];
extension String {

    /**
      Get the title case string.
     */
    var titleCase: String {
        get {
            return getTitleCaseString()
        }
    }

    // MARK: Private methods.

    /**
     Get title case string.

     - returns: The title case string regarding the lowercase words.
     */
    private func getTitleCaseString() -> String {
        struct Holder {
            static let lowercaseWords = ["a", "an", "and", "at", "but", "by", "else", "for",
                                         "from", "if", "in", "into", "is", "nor", "of", "off",
                                         "on", "or", "out", "the", "to", "via", "vs", "with"]
        }
        return replaceToLowercaseAllOccurrencesOfWords(Holder.lowercaseWords).capitalizeFirst
    }

    /**
     Replace to lowercase all occurrences of lowercase words.

     - parameter lowercaseWords: The lowercase words to replace.

     - returns: String with all occurrences replace to the lowercase words.
     */
    private func replaceToLowercaseAllOccurrencesOfWords(lowercaseWords: [String]) -> String {
        let capitalizedSelf = NSMutableString(string: self.capitalizedString)
        for word in lowercaseWords {
            if let lowercaseWordRegex = try? NSRegularExpression(pattern: "\\b\(word)\\b", options: .CaseInsensitive) {
                lowercaseWordRegex.replaceMatchesInString(capitalizedSelf,
                                                          options: NSMatchingOptions(),
                                                          range: NSMakeRange(0, capitalizedSelf.length),
                                                          withTemplate: word)
            }
        }
        return capitalizedSelf as String
    }

/**
     Capitalize first char.
     */
    private var capitalizeFirst: String {
        if isEmpty { return "" }
        var result = self
        result.replaceRange(startIndex...startIndex, with: String(self[startIndex]).uppercaseString)
        return result
    }

}
Другие вопросы по тегам