Как перебирать только те символы в строке, которые я действительно вижу?

Обычно я бы просто использовал что-то вроде str[i].

А если str = "☀️????????"?

str[i] не работает. for (x of str) console.log(x) тоже не работает. Он выводит всего 4 символа, хотя в строке явно только 2 смайлика.

Каков наилучший способ перебрать каждый символ, который я вижу в строке (и новые строки, я думаю), и ничего больше?

Идеальным решением будет возвращать массив из 2 символов: 2 смайлика и ничего больше. Заявленный дубликат и множество других решений, которые я нашел, не соответствуют этому критерию.


person thedayturns    schedule 22.04.2016    source источник
comment
Я думаю, вам следует проверить это сообщение в блоге: ссылка   -  person msencer    schedule 22.04.2016
comment
Вы говорите, что хотите захватить смайлик или пропустить его и найти следующего нормального персонажа?   -  person KevBot    schedule 22.04.2016
comment
@RaymondChen предложенный вами ответ кажется полифиллом для синтаксиса for...of, который, как я указал, не работает в этом случае. Но, пожалуйста, поправьте меня, если я ошибаюсь!   -  person thedayturns    schedule 22.04.2016
comment
@KevBot Я хотел бы запечатлеть смайлик как один символ. По сути, если я могу выбрать его как отдельный символ, я хотел бы захватить его как один символ.   -  person thedayturns    schedule 22.04.2016
comment
Предлагаемый ответ говорит, что for..of не может быть заполнен полифиллом. Предлагаемые ответы показывают, как разбить строку на кодовые точки. Если вы не хотите заполнять его полифилом, просто используйте его как бесплатную функцию.   -  person Raymond Chen    schedule 22.04.2016
comment
@RaymondChen Мой желаемый ответ должен быть длиной всего 2 символа (и смайлики, и ничего больше). Функция toCodePoints возвращает массив длины 4.   -  person thedayturns    schedule 22.04.2016
comment
Во-первых, ваше исходное утверждение неверно. for (x in str) console.log(x) печатает шесть символов (плюс дополнительный мусор, не относящийся к обсуждению), а не четыре, которые вы изначально заявляли. Это потому, что строка "☀️????????" состоит из шести кодовых единиц: "\u2600\ufe0f\ud83d\ude4c\ud83c\udffc". Это разбивается на четыре кодовых точки: U+2600 (ЧЕРНОЕ СОЛНЦЕ С ЛУЧАМИ), U+FE0F (ВАРИАНТ 16), U+1F64C (ЧЕЛОВЕК, ПОДНИМАЮЩИЙ ОБЕ РУКИ В ПРАЗДНОВАНИИ) и U+1F3FC (ЭМОДЖИ-МОДИФИКАТОР ФИТЦПАТРИКА, ТИП 3). . Похоже, вы хотите взломать графемы, что является более сложной проблемой.   -  person Raymond Chen    schedule 23.04.2016
comment
@RaymondChen Я сказал for (x of str), а не x in str именно потому, что of разбивается на кодовые точки, а не на символы. Графемы оказались здесь волшебным словом — как только я погуглил об этом, я быстро нашел достойную библиотеку для выполнения этой работы.   -  person thedayturns    schedule 23.04.2016
comment
См. мое решение, опубликованное по другому вопросу, в котором не учитываются астральные символы/суррогатные пары: stackoverflow.com/questions/1966476/   -  person hippietrail    schedule 05.07.2017


Ответы (2)


В конце концов я нашел ответ в виде этой безумной JS-библиотеки:

https://github.com/orling/grapheme-splitter

person thedayturns    schedule 22.04.2016

Вам нужно сделать свои собственные методы для астральных персонажей.

"foo????bar".match(/[\uD800-\uDBFF][\uDC00-\uDFFF]|./g);
// => ["f", "o", "o", "????", "b", "a", "r"]
person Amadan    schedule 22.04.2016
comment
Это работает не во всех случаях. Рассмотрим "foo????b☀️ar".match(/[\uD800-\uDBFF][\uDC00-\uDFFF]|./g);. - person thedayturns; 23.04.2016
comment
@thedayturns: Да, я рассмотрел только астральные символы, и именно здесь JavaScript по ошибке разбивает один символ Unicode на два символа JS. Пустая строка — это ВАРИАНТ 16 (U+FE0F), который является отдельным символом Unicode, но комбинируется с предыдущим; аналогичная проблема будет со всеми комбинированными символами, такими как COMBINING ACUTE ACCENT (U + 0301). Таким образом, чтобы решить эту проблему, вам понадобится целая библиотека, которая выходит за рамки ответа StackOverflow. - person Amadan; 23.04.2016