Я ищу самый простой способ конвертировать строку из формата camelback в формат Title Case.
Как изменить 'playerName' на 'Player Name'?
Я ищу самый простой способ конвертировать строку из формата camelback в формат Title Case.
Как изменить 'playerName' на 'Player Name'?
NSString *str = @"playerName";
NSMutableString *str2 = [NSMutableString string];
for (NSInteger i=0; i<str.length; i++){
NSString *ch = [str substringWithRange:NSMakeRange(i, 1)];
if ([ch rangeOfCharacterFromSet:[NSCharacterSet uppercaseLetterCharacterSet]].location != NSNotFound) {
[str2 appendString:@" "];
}
[str2 appendString:ch];
}
NSLog(@"%@", str2.capitalizedString);
Здесь более простая версия Swift. Я вложил его в расширение
extension String {
func stringFromCamelCase() -> String {
var string = self
string = string.stringByReplacingOccurrencesOfString("([a-z])([A-Z])", withString: "$1 $2", options: NSStringCompareOptions.RegularExpressionSearch, range: Range<String.Index>(start: string.startIndex, end: string.endIndex))
string.replaceRange(startIndex...startIndex, with: String(self[startIndex]).capitalizedString)
return string
}
}
Использование:
var str = "helloWorld"
str = str.stringFromCamelCase()
Попробуйте использовать замену регулярных выражений
NSString *modified = [input stringByReplacingOccurrencesOfString:@"([a-z])([A-Z])"
withString:@"$1 $2"
options:NSRegularExpressionSearch
range:NSMakeRange(0, input.length)];
Немного короче, используя NSCharacterSet:
__block NSString *str = @"myVerySpecialPlayerName" ;
// split at uppercase letters
NSArray *splitString = [str componentsSeparatedByCharactersInSet:
[NSCharacterSet uppercaseLetterCharacterSet]] ;
// get the uppercase letters
NSArray *upperCaseLetters = [str componentsSeparatedByCharactersInSet:
[[NSCharacterSet uppercaseLetterCharacterSet] invertedSet]] ;
// join with two spaces
str = [splitString componentsJoinedByString:@" "] ;
__block NSInteger offset = 0 ;
// replace each second space with the missing uppercase letter
[upperCaseLetters enumerateObjectsUsingBlock:^(NSString *character, NSUInteger idx, BOOL *stop) {
if( [character length] > 0 ) {
str = [str stringByReplacingCharactersInRange:NSMakeRange(idx+offset+1, 1) withString:character] ;
offset += 2 ;
}
}] ;
// & capitalize the first one
str = [str capitalizedString] ;
NSLog(@"%@", str) ; // "My Very Special Player Name"
Я думаю, вы можете решить эту проблему с помощью некоторых регулярных выражений. Посмотрите на этот похожий вопрос: iPhone dev: замените символы верхнего регистра в NSString пробелом и строкой
Хотя немного длинный, но эта категория для NSString должна делать трюк. Он прошел все мои тесты:
- (NSString *)splitOnCapital
{
// Make a index of uppercase characters
NSRange upcaseRange = NSMakeRange('A', 26);
NSIndexSet *upcaseSet = [NSIndexSet indexSetWithIndexesInRange:upcaseRange];
// Split our camecase word
NSMutableString *result = [NSMutableString string];
NSMutableString *oneWord = [NSMutableString string];
for (int i = 0; i < self.length; i++) {
char oneChar = [self characterAtIndex:i];
if ([upcaseSet containsIndex:oneChar]) {
// Found a uppercase char, now save previous word
if (result.length == 0) {
// First word, no space in beginning
[result appendFormat:@"%@", [oneWord capitalizedString]];
}else {
[result appendFormat:@" %@", oneWord];
}
// Clear previous word for new word
oneWord = [NSMutableString string];
}
[oneWord appendFormat:@"%c", oneChar];
}
// Add last word
if (oneWord.length > 0) {
[result appendFormat:@" %@", oneWord];
}
return result;
}
У меня была аналогичная проблема, ответы здесь помогли мне создать решение. У меня был массив, у которого был список меток, которые я хотел отображать в UITableView, по одной метке в строке.
Моя проблема заключалась в том, что я обработал эти метки из XML, возвращаемого действием SOAP, и я не знал о формате строк.
Во-первых, я ввел метод webstersx в метод. Это было здорово, но некоторые из этих ярлыков начинались с большой буквы, а некоторые - с верблюжьим футляром (например, некоторые строки, где exampleLabel
и другие, где exampleLabel
. Таким образом, это означало, что начиная с капитала было вставлено пространство перед строка.
Я преодолел это, обрезая пробелы от начала и конца строки, используя NSString stringByTrimmingCharactersInSet
.
Следующая проблема заключалась в использовании любых сокращений, таких как "ID" или "PNR Status", которые отображаются как "ID" и "PNR Status" в качестве заглавных букв, где, и совершенно правильно, подбираются и пробелы вставлен перед ним.
Я преодолел эту проблему, выполнив регулярное выражение, подобное запросу emdog4, в мой новый метод.
Вот мое законченное решение:
- (NSString *)formatLabel:(NSString *)label
{
NSMutableString *str2 = [NSMutableString string];
for (NSInteger i=0; i<label.length; i++){
NSString *ch = [label substringWithRange:NSMakeRange(i, 1)];
if ([ch rangeOfCharacterFromSet:[NSCharacterSet uppercaseLetterCharacterSet]].location != NSNotFound) {
[str2 appendString:@" "];
}
[str2 appendString:ch];
}
NSString * formattedString = [str2 stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]].capitalizedString;
formattedString = [formattedString stringByReplacingOccurrencesOfString:@"([A-Z]) (?![A-Z][a-z])" withString:@"$1" options:NSRegularExpressionSearch range:NSMakeRange(0, formattedString.length)];
return formattedString;
}
Затем я просто вызываю что-то вроде этого, например, которое вернет мою красиво отформатированную строку:
NSString * formattedLabel = [self formatLabel:@"PNRStatus"];
NSLog(@"Formatted Label: %@", formattedLabel);
Будет выводиться:
2013-10-10 10: 44: 39.888 Test Project [28296: a0b] Отформатированная метка: статус PNR
Если кому-то нужна версия Swift:
func camelCaseToTitleCase(s: NSString) -> String {
var newString = ""
if s.length > 0 {
newString = s.substringToIndex(1).uppercaseString
for i in 1..<s.length {
let char = s.characterAtIndex(i)
if NSCharacterSet.uppercaseLetterCharacterSet().characterIsMember(char) {
newString += " "
}
newString += s.substringWithRange(NSRange(location: i, length: 1))
}
}
return newString
}
Попытка быть более совместимой с юникодом
extension String {
func camelCaseToTitleCase() -> String {
return unicodeScalars.map(replaceCaptialsWithSpacePlusCapital).joined().capitalized
}
private func replaceCaptialsWithSpacePlusCapital(unichar: UnicodeScalar) -> String {
if CharacterSet.uppercaseLetters.contains(unichar) {
return " \(unichar)"
}
return "\(unichar)"
}
}
в то время как технически более короткий, более неэффективный
NSString *challengeString = @"playerName";
NSMutableString *rStr = [NSMutableString stringWithString:challengeString];
while ([rStr rangeOfCharacterFromSet:[NSCharacterSet uppercaseLetterCharacterSet]].location != NSNotFound) {
[rStr replaceCharactersInRange:[rStr rangeOfCharacterFromSet:[NSCharacterSet uppercaseLetterCharacterSet]] withString:[[NSString stringWithFormat:@" %@", [rStr substringWithRange:[rStr rangeOfCharacterFromSet:[NSCharacterSet uppercaseLetterCharacterSet]]]] lowercaseString]];
}
NSLog(@"%@", rStr.capitalizedString);
Не уверен, что это намного короче, чем websterx, но я считаю, что использование characterIsMember легче читать и понимать. Также добавлена проверка длины, чтобы исправить пробел раньше, если строка начинается с капитала.
NSString *str = @"PlayerNameHowAboutALongerString";
NSMutableString *str2 = [NSMutableString string];
for (NSInteger i=0; i<str.length; i++){
unichar ch = [str characterAtIndex:i];
if ( [[NSCharacterSet uppercaseLetterCharacterSet] characterIsMember:ch]) {
if (str2.length > 0 ) {
[str2 appendString:@" "];
}
}
[str2 appendString:[NSString stringWithCharacters:&ch length:1]];
}
NSLog(@"--%@--", str2.capitalizedString);
Принятый ответ не сработал у меня, потому что он не использует первую букву, и если первая буква уже заглавная, она добавляет постороннее пространство в начале. Вот моя улучшенная версия:
- (NSString *)titleFromCamelCaseString:(NSString *)input
{
NSMutableString *output = [NSMutableString string];
[output appendString:[[input substringToIndex:1] uppercaseString]];
for (NSUInteger i = 1; i < [input length]; i++)
{
unichar character = [input characterAtIndex:i];
if ([[NSCharacterSet uppercaseLetterCharacterSet] characterIsMember:character])
{
[output appendString:@" "];
}
[output appendFormat:@"%C", character];
}
return output;
}
Вот код Swift (код цели c от webstersx), спасибо!
var str: NSMutableString = "iLoveSwiftCode"
var str2: NSMutableString = NSMutableString()
for var i:NSInteger = 0 ; i < str.length ; i++ {
var ch:NSString = str.substringWithRange(NSMakeRange(i, 1))
if(ch .rangeOfCharacterFromSet(NSCharacterSet.uppercaseLetterCharacterSet()).location != NSNotFound) {
str2 .appendString(" ")
}
str2 .appendString(ch)
}
println("\(str2.capitalizedString)")
}
NSString *input = @"playerName";
NSString *modified = [input stringByReplacingOccurrencesOfString:@"(?<!^)[A-Z]" withString:@" $0" options:NSRegularExpressionSearch range:NSMakeRange(0, input.length)].capitalizedString;
Другое решение под Swift 2.2
extension String {
var stringFromCamelCase:String {
return (self as NSString).replacingOccurrences(
of: "([a-z])([A-Z])",
with: "$1 $2",
options: CompareOptions.regularExpressionSearch,
range: NSMakeRange(0, self.characters.count)
).uppercaseFirst
}
var uppercaseFirst: String {
return String(characters.prefix(1)).uppercased() + String(characters.dropFirst()).lowercased()
}
}
попробуйте использовать:
string.Split()
затем используйте букву cap в качестве токена