Swift countElements() возвращает неправильное значение, когда счётчик флагов смайликов
let str1 = ""
let str2 = "....."
println("\(countElements(str1)), \(countElements(str2))")
Результат: 1, 10
Но не должно ли str1 иметь 5 элементов?
Ошибка, кажется, произошла только тогда, когда я использую флаг Emoji.
2 ответа
Обновление для Swift 4 (Xcode 9)
Начиная с Swift 4 (протестировано с бета-версией Xcode 9) кластеры графемов разбиваются после каждого второго символа регионального индикатора, как это предусмотрено стандартом Unicode 9:
let str1 = ""
print(str1.count) // 5
print(Array(str1)) // ["", "", "", "", ""]
Также String
является коллекцией его символов (снова), поэтому можно получить количество символов с str1.count
,
(Старый ответ для Swift 3 и старше:)
Из "Границы 3 графемных кластеров" в "Стандартном приложении № 29 СЕГМЕНТАЦИЯ ТЕКСТА ЮНИКОДА": (выделение добавлено):
Устаревший кластер графем определяется как основание (например, A или カ), за которым следует ноль или более непрерывных символов. Один из способов думать об этом - это последовательность символов, которые образуют "стек".
Основой могут быть отдельные символы или любая последовательность символов Hangul Jamo, которые образуют слог Hangul, как определено D133 в Стандарте Unicode, или любая последовательность символов Regional_Indicator (RI). Символы RI используются парами для обозначения символов национального флага Emoji, соответствующих кодам стран ISO. Последовательности более двух символов RI должны быть разделены другими символами, такими как U + 200B ZWSP.
(Спасибо @rintaro за ссылку).
Стрелочный символ представляет расширенный кластер графем, поэтому (согласно этой ссылке) правильно, что любая последовательность символов региональных индикаторов считается одним символом.
Вы можете разделить "флаги" с помощью ZOOO WIDTH NON-JOINER:
let str1 = "\u{200C}"
print(str1.characters.count) // 2
или вставьте НУЛЕВОЕ ПРОСТРАНСТВО ШИРИНЫ:
let str2 = "\u{200B}"
print(str2.characters.count) // 3
Это решает также возможные двусмысленности, например, "" быть "или" "?
Смотрите также Как узнать, будут ли два смайлика отображаться как один смайлик? о возможном методе подсчета количества "составленных символов" в строке Swift, которая вернет 5
для тебя let str1 = ""
,
Вот как я решил эту проблему для Swift 3:
let str = "" //or whatever the string of emojis is
let range = str.startIndex..<str.endIndex
var length = 0
str.enumerateSubstrings(in: range, options: NSString.EnumerationOptions.byComposedCharacterSequences) { (substring, substringRange, enclosingRange, stop) -> () in
length = length + 1
}
print("Character Count: \(length)")
Это исправляет все проблемы с количеством персонажей и смайликами, и это самый простой метод, который я нашел.