Сравнение адресов: случай из практики

04.01.20

Разработка - Математика и алгоритмы

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

Прочитал статью infostart.ru/public/1175238/, а потом еще и комментарии к ней, и вспомнил, как я решал задачу примерно из той же серии. Правда, мне не требовалось раскладывать адрес на компоненты, хотя это могло бы быть одним из путей решения. Задача состояла в том, чтобы сравнить два адреса, представленных в виде строк, и решить, означают ли они одно и то же с некоторыми оговорками.

А главное препятствие заключалось как раз в том, о чем сказано в комментарии к упомянутой статье – крайне небрежный ввод сведений в компьютер.

Проблема

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

Здесь важно отметить, что речь идет о местных жителях. С одной стороны, это провоцирует сотрудников учреждения на всякие вольности, сокращения и упрощения, ибо «и так понятно», а с другой – позволяет нам делать некие предположения вероятностного характера для упрощения задачи.

Надо заметить, что в данном случае наши предположения – ни что иное, как ответ на «и так понятно», то есть попытка поставить себя на место сотрудника учреждения и представить, какую информацию он счел само собой разумеющейся и поэтому поленился внести в базу.

Так вот, однажды в учреждении возникла идея не только модернизировать базы данных, но и объединить их в одну. Причем данные, относящиеся к одному и тому же заявителю, следовало аккуратно свести в одну карточку.

Тут-то и возникла проблема, как определить, что сведения о заявителе из разных карточек, введенные абы как, означают одного и того же гражданина. То есть берем из разных баз две карточки с одними и теми же ФИО заявителя и с большой вероятностью обнаруживаем, что:

  • любые поля, кроме ФИО, могут оказаться незаполненными;
  • в любых заполненных полях могут быть допущены любые ошибки;
  • в полях адреса могут быть любые сокращения, понятные только местным жителям, а заодно еще и всякие примечания, показавшиеся кому-то крайне необходимыми в этом месте;
  • кроме того, гражданин мог обращаться в учреждение в разное время, а в период между обращениями сменить паспорт, адрес, телефон, обзавестись новыми родственниками, расстаться с прежними и т.д. и т.п.

Глядя на весь этот бардак, пришлось уточнить формулировку задачи:

  • необходимо разработать простой быстрый алгоритм, позволяющий свести к минимуму количество пар карточек с одинаковыми ФИО заявителя, по которым решение не может быть принято по формальным признакам;
  • следует иметь в виду, что объединение баз данных будет проведено лишь несколько раз, включая предварительное тестирование, после чего инструментальное ПО в основном станет ненужным вместе с исходными базами;
  • необходимо создать утилиту (внешнюю обработку), позволяющую человеку просматривать в объединенной базе оставшиеся пары карточек и при необходимости применять к ним процедуру объединения.

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

Сразу скажу, что в итоговой базе, содержащей примерно 15 тысяч карточек заявителей, осталось около 300 неразобранных пар карточек. Большинство из них затем были объединены вручную с помощью утилиты без изучения бумажных документов, а в остальных попросту не хватало заполненных полей.

Разумеется, сокращения, понятные только местным жителям, пришлось заранее выявить методом пристального взгляда и устранить с помощью небольшой обработки. А заодно вручную исправить отдельные ошибки, замеченные тем же пристальным взглядом. Такая подготовка данных шла итерациями, поскольку исправление очередной порции вольностей упрощало анализ того, что осталось.

Кстати, анализировать ошибки и сокращения проще всего оказалось в Экселе. Выгружаете справочник, сортируете по какому-нибудь столбцу или по нескольким, пробегаете по ним взглядом – и все видно, как на ладони. В глаза всегда бросается то, что выпадает из общего ряда, как, впрочем, и сам ряд.

Осталось найти формальные признаки, по которым алгоритм, не обладающий пристальным взглядом, определит, идет ли речь об одном и том же гражданине. Были выбраны три варианта:

1. Совпадают ФИО и данные паспорта (серия, номер, дата выдачи)

Это единственный надежный признак, не требующий оговорок.

2. Совпадают ФИО, дата рождения и адрес

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

3. Совпадают ФИО и адрес

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

Хорошо видно, что чем выше вероятность ложного срабатывания, свойственная тому или иному формальному признаку, тем ниже вероятность, что до него дойдет очередь.

Задача

Ну вот, собственно, мы и дошли до сравнения адресов, записанных с разной степенью небрежности. И здесь самое время вспомнить, что речь идет о местных жителях. Это дает нам право предполагать, что если не указаны населенный пункт, район и область, то скорее всего, это наш город и, разумеется, наш регион. Именно потому, что кому-то до нас это было «и так понятно».

То есть можно смело считать, что адреса

г. Наш город, ул. А, дом Б, …
ул. А, дом Б, …

означают одно и то же.

Вообще-то, в обсуждаемых базах встречаются заявители с пропиской из других городов, областей и даже государств с удивительно знакомыми названиями улиц. Но их очень мало, так что вероятность повторения сюжета известного новогоднего фильма пренебрежимо мала. Даже если бы такое случилось, эта ситуация проявилась бы косвенным образом, была бы обнаружена и вручную исправлена.

Сложнее, когда в адресе указан поселок, входящий в состав города. То есть адреса

г. Наш город, пос. Поселок, ул. А, дом Б, …
пос. Поселок, ул. А, дом Б, …
ул. А, дом Б, …
г. Наш город, ул. А, дом Б, …

опять-таки означают одно и то же, но очевидно это только местным жителям. К счастью, названия улиц уникальны в пределах всего города, включая поселки.

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

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

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

Кроме сложностей с содержанием адреса, есть еще и синтаксические неудобства. Хорошо бы упростить разбор слов и сокращений, указывающих вид объекта ("г.", "пос.", "ул." и т.д.), во всем их разнообразии, справиться с наличием и отсутствием запятых и прочих знаков препинания и т.д. и т.п. Автор упомянутой статьи смело берется за эту задачу, а я просто избавился от нее.

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

И еще одно предположение основано на том, что при обращении в то учреждение заявителю хочется гарантированно получить ответ. Следовательно, адрес, раз уж его ввели в базу, достаточно подробно указывает местонахождение заявителя. Он не заканчивается чем-то бóльшим, если требуется еще и что-то меньшее. То есть если требуется номер дома, то адрес обязательно содержит его, а не заканчивается городом или улицей. Это очень важная оговорка, без которой предложенное решение вообще бы не работало.

Решение

Ну так вот, решение очень простое и основано на всех без исключения предположениях, рассмотренных выше.

Из адреса выбрасываются все обозначения вида объекта. Специально для этого подготовлен длинный список бесполезных слов. Заодно выкидываются окончания, приписанные к числам. Подряд идущие пробелы и знаки препинания заменяются одной запятой. Ну, а что осталось в результате, преобразуется в верхний регистр.

Так получается формализованный адрес. Боюсь, на почте откажутся его понимать. Да нам и не надо.

После того, как оба адреса приведены к такому виду, осталось попытаться найти один формализованный адрес в другом как подстроку и наоборот. Если хотя бы одна из попыток удалась, считаем исходные адреса совпадающими.

Например, всем известный адрес

Москва, 3-я улица Строителей, д. 25, кв. 12

превращается в

МОСКВА,3,СТРОИТЕЛЕЙ,25,12

Кстати, названия вроде Усть-Кулом и Камень-на-Оби при таком преобразовании превращаются в УСТЬ,КУЛОМ и КАМЕНЬ,ОБИ.

Если во второй карточке будет тот же адрес в Ленинграде, сравнение даст отрицательный результат. А если просто

3-я улица Строителей, д. 25, кв. 12

то строка

3,СТРОИТЕЛЕЙ,25,12

будет найдена в первой строке, и процедура сочтет адреса совпадающими.

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

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

Необходимо сделать несколько замечаний по поводу лишнего текста. Из примера видно, что отбрасываются окончания, присоединенные к числам через тире. Как правило, такие окончания пишутся произвольно и поэтому только мешают сравнению. В то же время важно сохранить в адресе букву, дополняющую номер дома. Для этого необходимо заранее проверить, что между номером и буквой нет никаких других символов или пробела.

Кроме того, из формализованного адреса пропадают сокращения вроде "В.", "Н." и т.д., поэтому процедура сравнения адресов ничего не гарантирует, если "В." сравнивается с "Верхний", "Н." – с "Нижний", а "ул. М.Горького" с "ул. Максима Горького". Подобные ситуации должны быть исправлены еще в исходных данных.

Несомненно, предложенное решение спорное и состоит из одних недостатков. Можете даже не перечислять их в комментариях. Я сам подскажу, если кто еще не заметил.

Прежде чем применять это решение в общем случае, нужно крепко задуматься. В следующем разделе сказано, над чем.

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

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

И главное, я очень внимательно читал протоколы предварительного тестирования.

В результате все получилось.

Доказательство

Наверняка, возникает вопрос, каким образом из перечисленных предположений получается обоснование надежности или хотя бы приемлемости предложенного решения? Ответ дан ниже.

При дальнейших рассуждениях необходимо иметь в виду, что выборка данных резко ограничена тем, что адреса берутся из карточек, имеющих одинаковые ФИО заявителя. То есть мы исследуем остальные предположения и пользуемся словами вроде «обязательно», «никогда», «может быть, но вряд ли» внутри этого резко ограниченного подмножества.

1. Мы все привыкли писать адреса от большего к меньшему и считаем это само собой разумеющимся.

Это значит, что при записи адресов мы привыкли соблюдать иерархическую структуру адреса, причем перечислять уровни (объекты) в порядке вложенности от большего к меньшему. Можно считать это базовым принципом, закрепленным в нашей культуре на протяжении нескольких поколений. Нам представляется совершенно естественным описывать местонахождение в населенном пункте, последовательно «открывая матрешку».

2. То, что важно для понимания, редко отбрасывается за ненадобностью.

Отсюда следует вывод, что промежуточные уровни, без которых можно, но неудобно обходиться, с большой вероятностью будут присутствовать в адресе. Как правило, это относится к городским районам, как-либо обособленным на территории города. Использование этого уровня упрощает восприятие адреса людьми.
Ненадежность сделанного вывода связана с тем, что если названия улиц уникальны в пределах всего города, то для правильной адресации уровень городского района не требуется. И тогда он с легкостью может быть пропущен, если, конечно, речь не идет о личном восприятии территории или, к примеру, об ограничении зон ответственности.

Следствие 1

Из предположения 1 следует, что если несколько местных жителей напишут адрес одного и того же местного объекта, сообразуясь с собственными представлениями о знаках препинания, сокращениях и прочих вольностях и формальностях, во всех получившихся записях будет одинаковый порядок названий и номеров объектов.

Следовательно, оставив только названия и номера объектов, мы получим совершенно одинаковые записи адресов. В предложенном решении такая запись называется формализованным адресом.

А из предположения 2 следует, что с небольшой вероятностью состав объектов может отличаться в зависимости от того, присутствуют ли в адресе необязательные уровни и насколько они важны лично для того, кто пишет адрес. Это замечание требует внести в следствие поправку: с большой вероятностью получим одинаковые записи.

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

Это значит, что если в записи адреса отсутствуют верхние уровни, включая город, то можно считать ничтожно малой вероятность того, что в имеющихся у нас данных найдется такой же адрес в другом населенном пункте. Как раз при этом надо иметь в виду замечание об ограниченности выборки, сделанное вначале. Иными словами, случайные совпадения адресов достаточно надежно отсекаются несовпадением ФИО заявителя, а также предварительным использованием более надежных признаков.

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

Ответ простой – для этого надо быть уверенным, что адрес начинается именно с улицы или городского района (поселка). То есть мало того, что нужен список названий всех улиц и районов, так еще и требуется хороший алгоритм разбора произвольно записанного адреса, способный преодолеть все интуитивно понятные вольности. Достаточно было представить объем работы, чтобы предпочесть решение, которое вообще не требует анализа адреса и явного добавления отсутствующих данных.

4. В обсуждаемых базах адрес достаточно подробно указывает местонахождение заявителя.

Это действительно очень важная оговорка, без которой предложенное решение вообще не работает. Она означает, что ни один адрес, имеющийся в базе, не обрывается раньше того уровня, который необходим для поиска заявителя.

То есть, сравнивая две записи адреса одного и того же заявителя, взятые из карточек, мы получим совпадение на всех уровнях, необходимых для однозначного указания местонахождения заявителя.

Следствие 2

Из предположений 1, 3 и 4 следует, что если более короткий вариант формализованного адреса полностью содержится в более длинном, то они оба однозначно указывают одно и то же местонахождение заявителя.

Или, попросту говоря, адрес может не иметь начала, но всегда имеет конец, и у одинаковых адресов он совпадает.

Программный код

Как неинтересна книжка без картинок, так и рассуждения о программном коде неинтересны без самого кода. Он был написан для режима совместимости с 8.2.

Функция ФормализоватьАдрес(СтрокаАдрес, МассивСокращений)

	// Приводит запись адреса одной строкой в общепринятой произвольной форме к 
	// формату, позволяющему сравнить адреса
	
	// Возвращает строку с формализованной записью адреса
	
	СтрАдрес = ВРег(СтрокаАдрес);
	
	СтрАдрес = СтрЗаменить(СтрАдрес, ",", " ");
	СтрАдрес = СтрЗаменить(СтрАдрес, ".", " ");
	СтрАдрес = СтрЗаменить(СтрАдрес, "-", " ");
	СтрАдрес = СтрЗаменить(СтрАдрес, "/", " ");
	СтрАдрес = СтрЗаменить(СтрАдрес, "(", " ");
	СтрАдрес = СтрЗаменить(СтрАдрес, ")", " ");
	СтрАдрес = СтрЗаменить(СтрАдрес, ";", " ");
	СтрАдрес = СтрЗаменить(СтрАдрес, ":", " ");
	СтрАдрес = СтрЗаменить(СтрАдрес, "!", " ");
	СтрАдрес = СтрЗаменить(СтрАдрес, "?", " ");
	СтрАдрес = СтрЗаменить(СтрАдрес, "\", " ");
	СтрАдрес = СтрЗаменить(СтрАдрес, "№", " ");
	СтрАдрес = СтрЗаменить(СтрАдрес, """", " ");
	
	МассивАдрес = РазложитьСтрокуВМассивПодстрок(СтрАдрес, " ");
	
	РазмерМассива = МассивАдрес.Количество();
	
	Для Счетчик = 1 По РазмерМассива Цикл
		
		// Для удаления элементов массива обходим его с конца
		
		Индекс = РазмерМассива - Счетчик;
		
		Если МассивСокращений.Найти(МассивАдрес[Индекс]) <> Неопределено Тогда
		
			МассивАдрес.Удалить(Индекс);
		
		КонецЕсли;
		
	КонецЦикла; // Счетчик
	
	// Разделитель по умолчанию - ","
	
	Возврат ПолучитьСтрокуИзМассиваПодстрок(МассивАдрес);

КонецФункции // ФормализоватьАдрес()

Упомянутый здесь МассивСокращений – это тот самый список бесполезных слов, которые следует выкинуть из формализованного адреса. Массив предварительно заполняется отдельной процедурой, показанной ниже.

Функция РазложитьСтрокуВМассивПодстрок() позаимствована из общего модуля ОбщегоНазначенияЗК типовой конфигурации ЗиКБУ 1.0

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

Функция ПолучитьСтрокуИзМассиваПодстрок() позаимствована из общего модуля СтроковыеФункцииКлиентСервер типовой конфигурации БГУ 1.0. По умолчанию она вставляет в качестве разделителя запятую.

К функции ФормализоватьАдрес() есть дополнение, предназначенное для адресов учреждений, выдающих документы. Они ведь тоже переписаны абы как, а сравнивать приходится.

Функция ФормализоватьУчреждДок(Наименование, МассивСокращений)

	// Приводит наименование учреждения, выдавшего документ, записанное в 
	// общепринятой форме с общепринятыми сокращениями, к формату, позволяющему 
	// сравнить наименования
	
	// Возвращает строку с формализованной записью
	
	// Замена "ОУФМС" на "УФМС" выполняется в расчете на то, что варианты слова 
	// "Отдел" исключаются в формализованном адресе
	
	СтрАдрес = ВРег(Наименование);
	
	СтрАдрес = СтрЗаменить(СтрАдрес, "  ", " "); // Замена двух пробелов на один
	
	СтрАдрес = СтрЗаменить(СтрАдрес, "УПРАВЛЕНИЕМ ВНУТРЕННИХ ДЕЛ", "УВД");
	СтрАдрес = СтрЗаменить(СтрАдрес, "УПРАВЛЕНИЕ ВНУТРЕННИХ ДЕЛ", "УВД");
	СтрАдрес = СтрЗаменить(СтрАдрес, "ОТДЕЛОМ ВНУТРЕННИХ ДЕЛ", "ОВД");
	СтрАдрес = СтрЗаменить(СтрАдрес, "ОТДЕЛ ВНУТРЕННИХ ДЕЛ", "ОВД");
	СтрАдрес = СтрЗаменить(СтрАдрес, "ПОСЕЛКОВЫМ ОТДЕЛОМ МИЛИЦИИ", "ПОМ");
	СтрАдрес = СтрЗаменить(СтрАдрес, "ПОСЕЛКОВЫЙ ОТДЕЛ МИЛИЦИИ", "ПОМ");
	СтрАдрес = СтрЗаменить(СтрАдрес, "ОУФМС", "УФМС");
	
	Возврат ФормализоватьАдрес(СтрАдрес, МассивСокращений);

КонецФункции // ФормализоватьУчреждДок()

Ну и наконец, массив сокращений. Уже и не помню, почему я предпочел сначала создать массив, а потом заполнить его в процедуре, но ничто не мешает сделать функцию, выполняющую оба действия.

МассивСокращений = Новый Массив;
ЗаполнитьМассивСокращенийАдресов(МассивСокращений);

...

Процедура ЗаполнитьМассивСокращенийАдресов(МассивСокращений)

// Заполняет массив сокращений, используемых в почтовых адресах

// МассивСокращений - пустой одномерный массив

// Цифры в комментариях – приоритет строк в списке

МассивСокращений.Добавить(""); // 0
МассивСокращений.Добавить("Б"); // 1
МассивСокращений.Добавить("В"); // 1
МассивСокращений.Добавить("Г"); // 1
МассивСокращений.Добавить("Д"); // 1
МассивСокращений.Добавить("Е"); // 1
МассивСокращений.Добавить("И"); // 1
МассивСокращений.Добавить("Й"); // 1
МассивСокращений.Добавить("К"); // 1
МассивСокращений.Добавить("М"); // 1
МассивСокращений.Добавить("Н"); // 1
МассивСокращений.Добавить("П"); // 1
МассивСокращений.Добавить("Р"); // 1
МассивСокращений.Добавить("С"); // 1
МассивСокращений.Добавить("Т"); // 1
МассивСокращений.Добавить("Ш"); // 1
МассивСокращений.Добавить("Я"); // 1
МассивСокращений.Добавить("АЯ"); // 2
МассивСокращений.Добавить("БУЛ"); // 2
МассивСокращений.Добавить("ВО"); // 2
МассивСокращений.Добавить("ГОР"); // 2
МассивСокращений.Добавить("ДЕР"); // 2
МассивСокращений.Добавить("ИЙ"); // 2
МассивСокращений.Добавить("КВ"); // 2
МассивСокращений.Добавить("КОМ"); // 2
МассивСокращений.Добавить("КОМН"); // 2
МассивСокращений.Добавить("КОР"); // 2
МассивСокращений.Добавить("КОРП"); // 2
МассивСокращений.Добавить("КР"); // 2
МассивСокращений.Добавить("КТ"); // 2
МассивСокращений.Добавить("МЕСТ"); // 2
МассивСокращений.Добавить("МК"); // 2
МассивСокращений.Добавить("МКР"); // 2
МассивСокращений.Добавить("МКРН"); // 2
МассивСокращений.Добавить("НА"); // 2
МассивСокращений.Добавить("НАБ"); // 2
МассивСокращений.Добавить("НЕ"); // 2
МассивСокращений.Добавить("ОБ"); // 2
МассивСокращений.Добавить("ОБЛ"); // 2
МассивСокращений.Добавить("ОБЩ"); // 2
МассивСокращений.Добавить("ОЙ"); // 2
МассивСокращений.Добавить("ОТ"); // 2
МассивСокращений.Добавить("ПЕР"); // 2
МассивСокращений.Добавить("ПО"); // 2
МассивСокращений.Добавить("ПОС"); // 2
МассивСокращений.Добавить("ПР"); // 2
МассивСокращений.Добавить("РН"); // 2
МассивСокращений.Добавить("СТ"); // 2
МассивСокращений.Добавить("СТР"); // 2
МассивСокращений.Добавить("ТОВ"); // 2
МассивСокращений.Добавить("УЛ"); // 2
МассивСокращений.Добавить("УЧ"); // 2
МассивСокращений.Добавить("БУЛЬВАР"); // 3
МассивСокращений.Добавить("КОРПУС"); // 3
МассивСокращений.Добавить("ОБЩЕСТВО"); // 3
МассивСокращений.Добавить("ПЕРЕУЛОК"); // 3
МассивСокращений.Добавить("ПОСЕЛОК"); // 3
МассивСокращений.Добавить("ПРОЕЗД"); // 3
МассивСокращений.Добавить("ПРОСПЕКТ"); // 3
МассивСокращений.Добавить("СЕКЦИЯ"); // 3
МассивСокращений.Добавить("СТРОЕНИЕ"); // 3
МассивСокращений.Добавить("УЛИЦА"); // 3
МассивСокращений.Добавить("УЧАСТОК"); // 3
МассивСокращений.Добавить("ШОССЕ"); // 3
МассивСокращений.Добавить("АО"); // 4
МассивСокращений.Добавить("ПГТ"); // 4
МассивСокращений.Добавить("РК"); // 4
МассивСокращений.Добавить("ТП"); // 4
МассивСокращений.Добавить("ГОРОД"); // 5
МассивСокращений.Добавить("ГОРОДА"); // 5
МассивСокращений.Добавить("ГОРОДЕ"); // 5
МассивСокращений.Добавить("ГОРОДУ"); // 5
МассивСокращений.Добавить("КРАЕ"); // 5
МассивСокращений.Добавить("КРАЙ"); // 5
МассивСокращений.Добавить("КРАЮ"); // 5
МассивСокращений.Добавить("КРАЯ"); // 5
МассивСокращений.Добавить("ОБЛАСТИ"); // 5
МассивСокращений.Добавить("ОБЛАСТЬ"); // 5
МассивСокращений.Добавить("ОТДЕЛ"); // 5
МассивСокращений.Добавить("ОТДЕЛА"); // 5
МассивСокращений.Добавить("ОТДЕЛЕНИЕ"); // 5
МассивСокращений.Добавить("ОТДЕЛЕНИЕМ"); // 5
МассивСокращений.Добавить("ОТДЕЛОМ"); // 5
МассивСокращений.Добавить("РАЙОН"); // 5
МассивСокращений.Добавить("РАЙОНА"); // 5
МассивСокращений.Добавить("РАЙОНЕ"); // 5
МассивСокращений.Добавить("РАЙОНУ"); // 5

КонецПроцедуры // ЗаполнитьМассивСокращенийАдресов()

И напоследок небольшой лайфхак для написания таких кусков кода. Основная часть процедуры была создана в виде таблицы в Ворде, а затем таблица преобразована в текст. Цифры в комментариях ведь не просто так стоят. Они нужны для сортировки таблицы по приоритету слов.

 

См. также

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

Универсальные функции Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

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

21.05.2024    8006    dimanich70    77    

105

Валидация JSON через XDTO (включая массивы)

WEB-интеграция Универсальные функции Механизмы платформы 1С Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.

28.08.2023    10366    YA_418728146    7    

148

Печать непроведенных документов для УТ, КА, ERP. Настройка печати по пользователям, документам и печатным формам

Пакетная печать Печатные формы Адаптация типовых решений Универсальные функции Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Абонемент ($m)

Расширение для программ 1С:Управление торговлей, 1С:Комплексная автоматизация, 1С:ERP, которое позволяет распечатывать печатные формы для непроведенных документов. Можно настроить, каким пользователям, какие конкретные формы документов разрешено печатать без проведения документа.

2 стартмани

22.08.2023    2526    35    progmaster    8    

4

Расширение: Быстрые отборы через буфер [Alt+C] Копировать список, [Alt+V] Вставить список, [Ctrl+C] Копировать из файлов

Инструментарий разработчика Универсальные функции Платформа 1С v8.3 Конфигурации 1cv8 1С:Розница 2 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Зарплата и Управление Персоналом 3.x Абонемент ($m)

Копирует в буфер значения из списков, из ячеек отчетов, таблиц, настроек списков, других отборов и вставляет в выбранную настройку отбора. Работает с Объект не найден. Работает как в одной так и между разными базами 1С. Использует комбинации [Alt+C] Копировать список, [Alt+V] Вставить список. Также для копирования данных используется стандартная [Ctrl+C] (например из открытого xls, mxl, doc и т.п. файла скопировать список наименований)

1 стартмани

13.10.2022    16768    148    sapervodichka    112    

132

Система контроля ведения учета [БСП]

Универсальные функции Механизмы типовых конфигураций БСП (Библиотека стандартных подсистем) Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

В данном материале рассмотрим типовой алгоритм подсистемы контроля учета БСП в конфигурациях на примерах.

18.07.2022    7567    quazare    8    

110

Хитрости СКД. Часть 3

СКД Универсальные функции Программист Стажер Платформа 1С v8.3 Система компоновки данных Конфигурации 1cv8 Бесплатно (free)

Столкнулся с тем, что мне приходится писать гору отчетов. Во многих приходится использовать повторяющиеся приемы. Решил написать шпаргалку, которая, надеюсь пригодится не только мне. В этой статье: Объединение ячеек в отчете только на определенном уровне иерархии, Постобработка итогов в табличном документе, Скрытие колонок в зависимости от количества месяцев в периоде.

28.05.2022    9604    milkers    11    

96

Модули общего назначения - готовые полезные функции и процедуры конфигураций на БСП

Универсальные функции БСП (Библиотека стандартных подсистем) Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

В данной статье я рассматриваю несколько полезных "классических" функций и процедур для работы с данными, которые уже встроены в БСП и готовы к использованию.

25.04.2022    16036    quazare    11    

138
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. Идальго 229 04.01.20 21:34 Сейчас в теме
А не проще верифицировать "не нормализованную" адресную строку на тойже DaData, которая в структурированном виде вернёт адрес, ну или там информацию об ошибке и т.п.? Там вроде ещё и коды ФИАС и Кладр будут, что удобно, ну и сами же наименования улиц также могут меняться и прочее.
2. AnatolPopov 170 05.01.20 00:26 Сейчас в теме
(1) Я в то время не знал про DaData. Хотя, скорее всего, не стал бы использовать. В любом случае воспринял бы задачу как свою личную головную боль ;)
К тому же, обращение к каким-то там сервисам потребовало бы прописывания доступа, бодания с отделом ИБ, в общем, эта идея была бы отброшена сразу.
3. EliasShy 48 14.01.20 07:05 Сейчас в теме
Решал подобную задачу по адресам - через Google Geocoding Api получаю координаты адреса, саму строку адреса хэширую, и хэш с координатами сохраняю.
Новый адрес ищу по координатам - если совпадает - то адреса одинаковые
4. AnatolPopov 170 15.01.20 20:24 Сейчас в теме
(3) Сурово ;) Как я понимаю, такие сведения необходимо получать при внесении адреса в базу? И как быть с погрешностью измерений, с последующими поправками картографии? Предусмотрен какой-то допуск?

В моем случае надо было работать с тем, что дают, и не добавлять отсебятины, даже если очень хочется. Мое решение хорошо тем, что это тупая молотилка, которая просто сравнивает, что дали, ничего не придумывает, а мы можем быть уверены, что вероятность ложных отказов будет просто мала, а вероятность ложных срабатываний - ничтожно мала. Причем второе условие гораздо важнее первого. Это как раз тот случай, когда лучше недоделать, чем потом исправлять.
5. EliasShy 48 16.01.20 08:18 Сейчас в теме
(4) погрешность решается количеством знаков в широте и долготе.
Сервисы геокодирования достаточно точно описывают точку и хорошо работают по пользовательскому представлению адреса.

Сведения о геоданных получаются не для всех адресов, а для участвующих в процессе (в моем случае доставка грузополучателю).
В месяц порядка 200 запросов идет - они проходят по бесплатному порогу Google.

Ранее пользовались Яндексом, однако с недавних пор они бесплатный порог убрали.
6. ivangrant 10 03.09.21 11:19 Сейчас в теме
Всё не так однозначно. Улицы состоят порой из 2-4 слов. Ещё есть в названии улиц числа. Например, Улица 1905-го года. А есть где в городе и улица и переулок имеют одинаковые названия.
Насчет описания достаточно точной геопозиции - не всегда работает эта схема.
Например с магазинами, где на одном адресе их может быть несколько.
Геокодирование удобно, когда 2-3 точки на 1 кв.км. Если больше, можно сколько угодно подбирать точки, погрешности при сопоставлении будут возрастать.
7. AnatolPopov 170 03.09.21 16:39 Сейчас в теме
(6)
Улицы состоят порой из 2-4 слов. Ещё есть в названии улиц числа. Например, Улица 1905-го года. А есть где в городе и улица и переулок имеют одинаковые названия.

Поэтому требуется большая подготовительная работа по устранению всяких вольностей в адресах, приведению названий к одному виду. Довольно муторно. А "-го" в конце "1905-го" убирается при создании формализованного адреса.
Оставьте свое сообщение