Как сравнить символы, содержащие символы эмодзи? - PullRequest
0 голосов
/ 13 апреля 2019

Общий обзор:

У меня есть список имен, каждое имя - string&. Обычное действие, которое нужно выполнить со списком строк, - это сортировка строк в алфавитном порядке.

Один из способов сделать это состоит в том, чтобы преобразовать обе строки в один и тот же регистр, начать с первого символа в каждой строке и оценить символы, чтобы увидеть, что идет первым в алфавите вдоль строк if (char1 > char2), повторяя до тех пор, пока два сравниваемых символа не равны или не достигают последнего символа в более короткой строке.

Символы эмодзи всегда оцениваются в ... интересные ... char значения, которые при использовании алгоритма сортировки, подобного описанному выше, символы смайликов всегда сортируются так, чтобы они приходили перед буквенно-цифровые символы.

Цель: Произвольная сортировка строк эмодзи или строк, которые просто начинаются с эмодзи, до или после чисто буквенно-цифровых строк. Я хотел бы иметь возможность контролировать, где в алфавитном порядке сортируются символы / строки эмодзи: выбор после 'Z' / 'z' или перед 'A' / 'a'.

(Я не говорю, что хотел бы контролировать, где они отсортированы, до точки размещения их между другими произвольными символами, такими как 'p' и 'q', и я не говорю, что моя цель - контролировать, как смайлики упорядочены по сравнению с другими смайликами, просто для ясности.)

Код для демонстрации:

bool compareStringsIgnoreCase(std::string& str1, std::string& str2)
{
   int i = 0;
   while (i < str1.length() && i < str2.length())
   {
      char firstChar = tolower(first[i]);
      char secondChar = tolower(second[i]);

      int firstCharAsInt = firstChar;
      int secondCharAsInt = secondChar;

      if (firstCharAsInt < secondCharAsInt)
           return true;
      else if (firstCharAsInt > secondCharAsInt)
           return false;
      i++;
   }
   return (str1.length() < str2.length());
}

При использовании str1 = "Abc" и str2 = ?, когда i = 0, остальные значения следующие: firstChar = 'a'

secondChar = '\xf0'

firstCharAsInt = 97

secondCharAsInt = -16

С этими значениями имеет смысл, что firstCharAsInt > secondCharAsInt, и поэтому функция возвращает true, и строка emoji сортируется так, чтобы быть перед строкой "Abc". Опять же, я бы хотел иметь возможность сортировать смайлики по буквенно-цифровым символам - вопрос в том, как?

Я опробовал несколько смайликов, и их значения "char как int" всегда отрицательны. Отличаются ли эмоджи от других char в этом смысле? Если так, то это может быть простой и легкой проверкой, которая может идентифицировать их, чтобы разместить их после других символов. Открыт и для других подходов.

Спасибо

Ответы [ 2 ]

2 голосов
/ 13 апреля 2019

Emojis - это символы Unicode, поэтому при условии, что ваши строки закодированы как UTF-8, тогда самый простой способ сравнить их - преобразовать их в std::wstring. Вы можете сделать это, используя std::codecvt. Хотя это не рекомендуется в C ++ 17, в настоящее время нет удобной замены.

Итак, можно сделать:

#include <string>
#include <codecvt>
#include <locale>
#include <cctype>

std::wstring widen (const std::string &s)
{
    std::wstring_convert <std::codecvt_utf8 <wchar_t>, wchar_t> convert;
    return convert.from_bytes (s);
}

void lower_case_string (std::wstring &ws)
{
    for (auto &ch : ws)
        ch = tolower (ch);
}

// Return true if s1 == s2 (UTF-8, case insensitive)
bool compare (const std::string &s1, const std::string &s2)
{
    std::wstring ws1 = widen (s1);
    lower_case_string (ws1);
    std::wstring ws2 = widen (s2);
    lower_case_string (ws2);
    return ws1 == ws2;
}

Хотя обратите внимание, что функция сравнения, которую можно использовать для сортировки, будет s1 < s2.

Живая демоверсия

0 голосов
/ 13 апреля 2019

Чтобы ответить на мой предложенный подход: эмодзи не уникальны тем, что их значения "char as int" отрицательны.

Другие символы, такие как, например, '§', также оцениваются как отрицательные, в данном случае -62, и поэтому сортируются перед буквенно-цифровыми символами.

Проверка этих отрицательных значений и нацеливание их на порядок сортировки будет работать для изменения порядка сортировки смайликов , но изменит порядок сортировки других посторонних символов какну , что делает этот подход несовершенным решением исходной цели.

Простой и понятный способ сделать это - привести значения char как int к unsigned ints.Отрицательные значения после дополнения до двух будут приведены к высоким положительным значениям и, таким образом, отсортированы по другим положительным значениям.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...