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

Публикация № 1176209

Разработка - Практика программирования

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

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

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

Ранее пользовались Яндексом, однако с недавних пор они бесплатный порог убрали.
Оставьте свое сообщение

См. также

Использование программных перечислений, ч.1: строковые константы Промо

Практика программирования v8 1cv8.cf Бесплатно (free)

Часто ли у вас возникает необходимость в коде выполнять сравнение на строку?

10.12.2016    37236    unichkin    74    

Программная работа с настройками СКД

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Нюансы программной работы с настройками системы компоновки данных в отчетах и динамических списках. Обзор всех видов настроек компоновки. Что в каких случаях правильно применять. В качестве примера рассмотрена работа с отборами и группировками.

27.01.2020    25562    ids79    26    

[СКД] Программное создание схемы компоновки данных

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Сделаем отчет на СКД полностью программно, без использования макета "схема компоновки данных".

15.01.2020    23037    John_d    22    

Последовательности событий. Шпаргалка

Практика программирования v8 Россия Бесплатно (free)

Собрал информацию о событиях/подписках/расширениях в одном месте.

30.12.2019    17596    kuzyara    33    

Вспомогательные инструкции в коде 1С Промо

Практика программирования v8 1cv8.cf Бесплатно (free)

Помогаем редактору кода 1С помогать нам писать и анализировать код.

15.10.2018    30095    tormozit    100    

Универсальные функции: разложение произвольной строки адреса в структуру

Практика программирования Универсальные функции v8 1cv8.cf Абонемент ($m)

Процедуры и функции раскладывают произвольную строку адрес в структуру по ключевым словам.

1 стартмани

30.12.2019    3519    vik070777    10    

30 задач. Странных и не очень

Практика программирования v8 Бесплатно (free)

30 задач на знание языка программирования 1С и некоторого поведения платформы. Маленьких. Странных и не очень.

02.12.2019    16876    YPermitin    72    

Как передать IP адрес, который вызвал HTTP запрос в 1C (для веб-сервера Apache)

Практика программирования v8 Бесплатно (free)

Столкнулся с задачей получения IP адреса, который вызывает http сервис 1С. Итак, решение:

22.11.2019    8271    Sibars    19    

Оформление и рефакторинг сложных логических выражений Промо

Практика программирования v8 Россия Бесплатно (free)

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

20.09.2012    77851    tormozit    131    

Таблица значений. Нюансы

Практика программирования v8 Бесплатно (free)

Обзор некоторых аспектов использования общеизвестного инструмента 1С.

01.10.2019    32531    Yashazz    50    

О программе Postman для тестирования API и для чего она нужна 1С-нику

Практика программирования Программное обеспечение (software) v8 Бесплатно (free)

Для чего нужна программа Postman для тестирования API и какая от него польза для 1С-программиста.

24.09.2019    11613    budidich    28    

[Шпаргалка] Программное создание элементов формы

Практика программирования Работа с интерфейсом v8 1cv8.cf Бесплатно (free)

Программное создание практически всех популярных элементов формы.

06.09.2019    48530    rpgshnik    63    

Запись значения в поле ввода/формы со срабатыванием события ПриИзменении Промо

Практика программирования v8 1cv8.cf Россия Бесплатно (free)

Иногда возникает необходимость после записи значения в какое либо поле ввода/формы вызвать для него обработчик события ПриИзменении, а о вызове самого события приходится только мечтать. В этой статье приводится программный способ вызова этого события.

11.07.2007    48197    tormozit    41    

Агрегатные функции СКД, о которых мало кто знает

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Пользуетесь ли Вы всеми возможными агрегатными функциями, которые предоставляет система компоновки данных? Если Вы используете только: СУММА, КОЛИЧЕСТВО, МИНИМУМ, МАКСИМУМ, СРЕДНЕЕ, то эта статья для Вас.

05.09.2019    48461    ids79    54    

Регистры бухгалтерии. Общая информация

Практика программирования Математика и алгоритмы v8 v8::БУ БУ Бесплатно (free)

Общая информация о внутреннем устройстве регистров бухгалтерии.

05.09.2019    27926    YPermitin    24    

Три костыля. Сказ про фокусы в коде

Практика программирования v8 Бесплатно (free)

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

03.09.2019    25336    YPermitin    80    

Как сделать из &НаКлиентеНаСервереБезКонтекста почти &НаКлиентеНаСервере Промо

Практика программирования v8 1cv8.cf Россия Бесплатно (free)

Как сделать метод формы, доступный на клиенте и на сервере одновременно, и сохранить при этом удобство разработки

10.09.2017    44635    tormozit    74    

Отслеживание выполнения фонового задания

Практика программирования Универсальные функции Разработка v8 1cv8.cf Бесплатно (free)

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

17.08.2019    31169    ids79    16    

Функции СКД: ВычислитьВыражение, ВычислитьВыражениеСГруппировкойМассив

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Подробное описание и использование внутренних функций системы компоновки данных: Вычислить, ВычислитьВыражение, ВычислитьВыражениеСГруппировкойМассив, ВычислитьВыражениеСГруппировкойТаблицаЗначений.

08.08.2019    79782    ids79    49    

Фоновое выполнение кода в 1С - это просто

Практика программирования v8 1cv8.cf Бесплатно (free)

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

02.08.2019    34462    avalakh    22    

Выгрузка документа по условию Промо

Практика программирования Разработка v8 Бесплатно (free)

Что делать, если документы нужно выгружать не все подряд, а по какому-то фильтру: статусу, дате, набору условий... А что если он соответствовал этим условиям, а потом перестал? А если потом опять начал? Такие ситуации заставили попотеть не одного программиста.

25.04.2019    16012    m-rv    2    

Разбираемся с параметрами редактирования СКД

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Связь по типу, Параметры выбора, Связи параметров выбора

31.07.2019    23299    json    13    

СКД - наборы данных и связи между ними, создание собственной иерархии, вложенные отчеты

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Набор данных объект. Использование в схеме компоновки нескольких наборов данных. Различные варианты связи наборов: объединение, соединение. Использование иерархии в отчетах на СКД. Создание собственной иерархии, иерархия детальных записей. Использование вложенных схем в отчетах на СКД.

26.07.2019    58284    ids79    11    

СКД - использование расширений языка запросов, секция ХАРАКТЕРИСТИКИ

Инструментарий разработчика Практика программирования v8 v8::СКД Бесплатно (free)

Автоматическое и не автоматическое заполнение полей компоновки данных. Использование расширений языка запросов для СКД «{…}», секция ВЫБРАТЬ, секция ГДЕ, параметры виртуальных таблиц. Автоматизированное использование дополнительных данных в запросе: секция ХАРАКТЕРИСТИКИ.

17.07.2019    35427    ids79    27    

Как прикрутить ГУИД к регистру сведений Промо

Практика программирования Перенос данных из 1C8 в 1C8 Разработка v8 Бесплатно (free)

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

16.04.2019    20140    m-rv    17    

Регистры сведений. За кулисами

Практика программирования Разработка v8 1cv8.cf Бесплатно (free)

Небольшие заметки по внутреннему устройству регистров сведений.

09.07.2019    25864    YPermitin    14    

"Меньше копипаста!", или как Вася универсальную процедуру писал

Практика программирования Разработка v8 v8::СКД 1cv8.cf Бесплатно (free)

Программист Вася разбирает подход создания универсальных методов на примере программного вывода СКД.

04.07.2019    19554    SeiOkami    50    

Работа с настройками системы компоновки данных

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

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

02.07.2019    45538    ids79    17    

Как сделать запрос на изменение данных Промо

Практика программирования v8 v8::Запросы 1cv8.cf Бесплатно (free)

В статье приведены особенности внутренней архитектуры и примеры работы с расширением языка запросов 1С.

01.06.2018    30479    m-rv    21    

Создание отчетов с помощью СКД - основные понятия и элементы

Практика программирования Математика и алгоритмы v8 v8::СКД Бесплатно (free)

Основные принципы работы СКД. Понятия схемы компоновки и макета компоновки. Описание основных элементов схемы компоновки: наборы данных, поля, вычисляемые поля, ресурсы, параметры.

25.06.2019    51747    ids79    25    

Многопоточное ускорение однопользовательских нагрузок в 1С + Microsoft SQL Server 2017

Практика программирования Производительность и оптимизация (HighLoad) v8 v8::Запросы Бесплатно (free)

Взаимодействие с Microsoft SQL Server нередко вызывает трудности у 1С-ников, а потому интересны любые моменты, связанные с его использованием. О своем опыте работы с новым SQL Server 2017 участникам конференции Infostart-2018 рассказал директор ООО «Аналитика софт» Дмитрий Дудин.

11.06.2019    24838    dmurk    145    

Регистры накопления. Структура хранения в базе данных

Практика программирования Разработка v8 1cv8.cf Бесплатно (free)

Структура хранения регистров накопления в базе данных для платформы 1С:Предприятие 8.x. Первая часть в серии публикаций.

16.05.2019    42468    YPermitin    30    

Метод формирования движений в типовых регистрах нетиповыми регистраторами Промо

Практика программирования v8 1cv8.cf Бесплатно (free)

Вариант решения задач с проведением по типовым регистрам нетиповыми регистраторами. Зачем - чтобы при сравнении конфигурации не обращать внимание на свойства регистров и исключить вероятность допущения горькой оплошности при обновлении информационных баз, заменив типы регистраторов основной конфигурации типами конфигурации поставщика. Для программных продуктов, имеющих в своем составе метаданных документ "Корректировка регистров"("Корректировка записей регистров").

05.12.2017    28203    itriot11    34    

О расширениях замолвите слово...

Практика программирования Разработка v8 Бесплатно (free)

О чём стоит задуматься при принятии решения о создании расширения конфигурации…

07.04.2019    35147    ellavs    126    

Git-репозитории для 1С-кода (опыт использования при небольших проектах)

Практика программирования v8 Бесплатно (free)

Инструкции по взаимодействию с Git-репозиторием, которые писались для тех наших программистов, которые вообще никогда не работали с Git (руководства в духе "Как получить код из git-репозитория?", "Как отправить код в git-репозиторий")...

28.03.2019    27296    ellavs    89    

Трюки с внешними источниками данных

Практика программирования Разработка v8 1cv8.cf Бесплатно (free)

Некоторые трюки для преодоления ограничений внешних источников данных.

14.03.2019    31155    YPermitin    53    

Использование классов .Net в 1С для новичков Промо

Практика программирования Разработка внешних компонент Универсальные функции v7.7 v8 Бесплатно (free)

Руководство для новичков. Написав статью http://infostart.ru/public/238584/, я понял, что многие не понимают того, что написано. Поэтому в этой статье постараюсь более подробно остановиться на азах и без кода на вражеском языке (C#)

27.01.2016    76204    Serginio    108    

Ошибки при работе с хранилищем конфигурации и способы их решения

Практика программирования v8 Бесплатно (free)

В статье собраны наиболее распространенные ошибки при работе с хранилищем конфигурации и способы их обхода и решения.

01.03.2019    38657    Смешной 1С    28    

Разработка и сценарное тестирование с Vanessa-ADD. Отчетность Allure. Автоматизация запуска сценариев

Практика программирования Vanessa Automation v8 Россия Бесплатно (free)

Формируем отчетность о результатах выполнения сценариев. Автоматизируем запуск.

26.02.2019    21784    Vladimir Litvinenko    27    

Автоматические и управляемые блокировки применительно к типовым конфигурациям 1С Промо

Математика и алгоритмы Практика программирования v8 v8::blocking 1cv8.cf Бесплатно (free)

Основные принципы работы с режимами автоматических и управляемых блокировок в 1С Предприятие 8. Теория и применение в типовых конфигурациях: БП, УТ, ЕРП

10.11.2018    34528    ids79    40    

Возможности типовых шаблонов ограничения доступа на уровне записей (RLS)

Практика программирования БСП (Библиотека стандартных подсистем) Роли и права v8 v8::Права Бесплатно (free)

Краткий обзор применения типовых шаблонов ограничения доступа на уровне записей в конфигурациях, созданных на базе БСП: #ПоЗначениям, #ПоНаборамЗначений, #ПоЗначениямРасширенный, #ПоЗначениямИНаборамРасширенный

03.02.2019    38920    ids79    9    

Тестер: частые вопросы Промо

Практика программирования v8 Бесплатно (free)

Ошибкам бой - тесты норма жизни!

25.07.2018    29173    grumagargler    28    

EnterpriseData – часть 2. Процесс выгрузки данных

Практика программирования Обмен через XML v8 v8::УФ Россия Бесплатно (free)

Основные этапы выгрузки данных через ED, обработчики событий выгрузки, правила обработки данных, правила конвертации объектов, конвертация свойств первого и второго этапов, процедуры БСП, используемые при выгрузке данных, структура «КомпонентыОбмена».

26.12.2018    26613    ids79    31    

Новый подход к обмену данными EnterpriseData

Практика программирования Обмен через XML v8 v8::УФ Россия Бесплатно (free)

Хочу предложить Вашему вниманию цикл статей, посвященных обмену данными через универсальный формат (EnterpriseData или ED).

14.12.2018    41089    ids79    72    

EnterpriseData - пример доработки правил конвертации без использования КД 3.0 в расширении конфигурации

Практика программирования Обмен через XML v8 v8::УФ БП3.0 УТ11 Россия Бесплатно (free)

В статье подробно описан реальный пример доработки обмена данными через EnterpriseData (универсальный формат обмена) между конфигурациями УТ 11.4 и Бухгалтерия 3.0

16.11.2018    36760    ids79    42    

Ускоряем 1С: модули с повторным использованием возвращаемых значений Промо

Практика программирования v8 Бесплатно (free)

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

04.09.2017    52490    m-rv    61    

Программное заполнение пользовательских параметров и отборов СКД

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Публикация представляет из себя краткие примеры того, как можно заполнять параметры СКД программно так, чтобы все параметры и отборы были доступны в быстрых настройках и в обычных (типовых) настройках параметров и отборов СКД.

13.11.2018    46889    Unk92    25