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)")

Это исправляет все проблемы с количеством персонажей и смайликами, и это самый простой метод, который я нашел.

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