Сопоставление названий стран и синонимы — это задача о том, как понять, что два разных набора букв означают один и тот же объект. Сложность не в сравнении строк, а в том, что сравнивать приходится неполные и по-разному оформленные сведения. Пока не решено, какое написание считается основным, любое сравнение будет догадкой.
Разберём, откуда берётся разнообразие написаний, почему порядок приведения к общему виду важен, когда неточное сравнение приносит вред и почему хранить нужно код, а не название.
Почему у одной страны так много написаний?
Причины разнообразия вполне предсказуемы, и их полезно знать, чтобы не считать каждое расхождение случайной ошибкой.
Первая — язык. Официальное название на языке страны почти всегда отличается от названия, принятого в международных документах. Оба варианта правильны, просто используются в разных обстоятельствах.
Вторая — полнота. Есть полное официальное наименование и есть короткое, употребительное. В обычном тексте используется короткое, в торжественном документе — полное.
Третья — история. Государство могло быть переименовано, и прежнее название продолжает жить в старых документах, в привычках людей и в устаревших справочниках.
Четвёртая — способы передачи символов другого алфавита. Одно и то же название может передаваться разными системами, и обе передачи встречаются в реальных данных.
Пятая — сокращения и аббревиатуры. В отраслевых документах используются короткие формы, которых нет ни в одном официальном перечне.
Наконец, шестая и самая частая причина — обычные опечатки и слитное написание служебных слов. Именно на них приходится основная масса несовпадений.
Почему сначала каноническое имя, а потом сравнение?
Каноническое имя — это то единственное написание, которое считается основным внутри вашей системы. Всё остальное — узнаваемые варианты, которые к нему приводятся.
Порядок важен потому, что без основного написания невозможно определить, что означает совпадение. Если два варианта совпали, но неизвестно, к чему они оба относятся, результат сравнения ничего не даёт: нельзя ни отобразить значение, ни сохранить его, ни объяснить пользователю.
Каноническое имя решает сразу несколько задач. Оно даёт точку, к которой сводятся варианты. Оно даёт значение для отображения. Оно же становится основой для сравнения: сравнивать нужно не любые два написания между собой, а каждое написание с каноническим.
Отсюда практическое следствие: таблица вариантов должна быть плоской. Не «вариант А похож на вариант Б», а «вариант А относится к такой-то записи». Плоская таблица допускает проверку и не порождает цепочек, где написание постепенно уезжает от исходного.
Ещё одно следствие: каноническое имя не должно выбираться автоматически по первому встреченному значению. Если оно определяется порядком поступления данных, то в двух системах оно окажется разным, и обмен данными между ними сломается.
В каком порядке приводить к общему виду?
Порядок операций — источник самых неприятных дефектов в этой области, потому что перестановка двух шагов даёт разный результат, а внешне они выглядят равнозначными.
Общее правило такое: сначала нормализуется форма записи символов, затем производится сравнение, а отображение всегда сохраняет исходный вид. Если шаги перепутать — например, сравнивать до нормализации, — появятся пары, которые «выглядят одинаково, но не совпадают». Это самая частая жалоба в подобных системах.
Что стоит продумать явно:
- Порядок нормализации и сравнения. Нормализация должна предшествовать сравнению, а не следовать за ним.
- Учёт регистра. Приведение к единому регистру нужно для сравнения, но не для отображения.
- Знаки над буквами. Их снятие помогает сопоставлению, но лишает значение исходного вида, если применять его к тому, что показывается пользователю.
- Пробелы и разделители. Разное количество пробелов и разные тире между частями названия — обычное дело; сравнение должно быть к ним устойчиво.
- Служебные слова. В одних языках перед названием ставится артикль, в других нет. Убирать их при сравнении стоит только там, где это не создаёт двусмысленности.
Важно, чтобы вся эта последовательность была одной функцией, а не набором мест, где каждое поступает по-своему. Иначе один путь сопоставления начнёт считать два написания одинаковыми, а другой — разными.
Когда неточное сравнение приносит вред?
Неточное сравнение кажется удобным: оно позволяет узнать название даже при опечатке. Но у него есть свойство, о котором легко забыть — оно ошибается в обе стороны.
Ложное совпадение опаснее пропущенного. Если система не узнала название, пользователь увидит сообщение и поправит ввод. Если система узнала неправильно и молча подставила другой объект, ошибка попадёт в данные и обнаружится гораздо позже — возможно, уже в отчёте или в документе.
Риск особенно велик там, где рядом существуют похожие названия: короткие формы, отличающиеся одним словом, или территории со схожими наименованиями. Именно на них неточное сравнение склонно сливать два разных объекта в один.
Поэтому разумная граница такая: неточное сравнение используется для предложения вариантов, а не для принятия решения. Система может показать пользователю два-три близких названия и попросить выбрать, но не должна выбирать за него, когда совпадение неполное.
Полезно также вести счётчик случаев, когда неточное сравнение сработало. Если таких случаев много, это сигнал, что таблица вариантов неполна, и правильнее дополнить её, чем расширять неточность.
Почему хранят код, а не название?
Название — признак, который меняется. Код — признак, который для данной записи остаётся стабильным.
Если в записи хранится название, то при переименовании все существующие данные окажутся привязаны к устаревшему написанию. Придётся либо переписывать прошлые записи, либо поддерживать два написания одновременно и объяснять каждому читателю отчёта, что они означают одно и то же.
Если хранится код, переименование затрагивает только отображаемое значение. Прошлые записи продолжают ссылаться на тот же объект, и ничего переписывать не нужно.
Из этого следуют три правила. Код — ключ, название — представление. Название никогда не участвует в однозначной идентификации записи. Для отображения берётся то написание, которое соответствует языку интерфейса, а не то, что когда-то попало в данные.
Отдельно стоит сказать про языковые соответствия. Отображение названия на разных языках должно определяться данными или стандартной библиотекой локализации, а не жёстко прописанными парами «язык — написание». Жёсткие пары быстро расходятся с реальностью и требуют правки кода при каждом изменении.
Что важно разработчику
Первое: сделайте таблицу вариантов проверяемой. У каждой записи должно быть указано, откуда она взялась и когда добавлена. Без этого невозможно понять, почему конкретное написание считается относящимся к конкретной стране.
Второе: не допускайте, чтобы вариант ссылался на вариант. Только на каноническую запись. Цепочки ссылок приводят к тому, что добавление одного варианта незаметно меняет смысл другого.
Третье: покройте проверками пять случаев — попадание в таблицу вариантов, различие регистра, присутствие и отсутствие знаков над буквами, явную опечатку и пустое значение. Эти пять покрывают почти все обращения на практике.
Четвёртое: определите, что система делает при неоднозначности. Молчаливый выбор одного из нескольких подходящих вариантов — самое дорогое решение из возможных, потому что его последствия не видны в момент совершения.
Что делать дальше
Начните с инвентаризации: выпишите, какие написания одного и того же объекта уже встречаются в ваших данных. Скорее всего, самых частых окажется не два, а больше.
Общую рамку даёт каталог стран и регионов: там видно, что основой служит устойчивый признак, а не написание. По соседству полезно посмотреть на тестирование поля выбора страны, поскольку именно через него варианты написания чаще всего попадают в систему, и на страну и язык: смешение этих двух слоёв — вторая по частоте причина ошибок сопоставления.
Таблица вариантов, списки написаний и примеры опечаток в этой статье вымышлены и приведены только для объяснения порядка работы. Они не воспроизводят ни один официальный перечень наименований и не являются справочным источником.