Нечеткие адреса

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

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

Мое текущее решение заключается в следующем:

matches = [];
foreach ($classifications as $classification)
{
$classification = $stringMatchingService->standardize($classification, $stringMatchingService->isClassification());
$shortest = -1;
$closest = '';
$cnt = 0;
foreach ($lines as $line)
{
$line = $stringMatchingService->standardize($line, $stringMatchingService->isRTT());
if ($classification[CLASSIFICATION_POSTCODE] != $line[RTT_POSTCODE]) {
continue;
}

$lev = levenshtein($classification[CLASSIFICATION_SUBURB], $line[RTT_SUBURB]);
if ($lev == 0) {
$matches[$classification[CLASSIFICATION_SUBURB]] = $line[RTT_SUBURB];
$cnt++;
break;
}

if ($lev <= $shortest || $shortest < 0) {
//set the closest match and distance
$closest = $line[RTT_SUBURB];
$shortest = $lev;
}

if ($cnt == count($lines)) {
$matches[$classification[CLASSIFICATION_SUBURB]] = $closest;
}
$cnt++;
}

}
print_r(count($matches));

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

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

Любая помощь приветствуется,

Спасибо!

РЕДАКТИРОВАТЬ:
Размер $ классификации 12000 строк и размер $ строк 17000 строк. Функция стандартизации выглядит следующим образом:

 public function standardize($line, $dataSet)
{
switch ($dataSet) {
case self::CLASSIFICATIONS:
if (!isset($line[9], $line[10]) || empty($line[9]) || empty($line[10])) {
continue;
}
$suburb = $line[9];
$suburb = strtoupper($suburb);
$suburb = str_replace('EXT', '', $suburb);
$suburb = str_replace('UIT', '', $suburb);
$suburb = preg_replace('/[0-9]+/', '', $suburb);

$postCode = $line[10];
$postCode = str_pad($postCode, 4,'0', STR_PAD_LEFT);
$line[9] = $suburb;
$line[10] = $postCode;
return $line;
case self::RTT:
if (!isset($line[1], $line[0]) || empty($line[1]) || empty($line[0])) {
continue;
}
$suburb = $line[1];
$suburb = strtoupper($suburb);
$suburb = str_replace('EXT', '', $suburb);
$suburb = str_replace('UIT', '', $suburb);
$suburb = preg_replace('/[0-9]+/', '', $suburb);
$postCode = $line[0];
$postCode = str_pad($postCode, 4,'0', STR_PAD_LEFT);
$line[1] = $suburb;
$line[0] = $postCode;
return $line;
}

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

0

Решение

Проблема здесь для каждого $classifications линия, вы проверяете, совпадают ли строки в $line, = 12000 * 17000 …

Итак, я не знаю структуру ваших массивов, но вы можете использовать array_filter,

$matches = array_filter($classifications, function ($entry) use ($lines) {

foreach ($lines as $line)
{
$lev = levenshtein($entry[CLASSIFICATION_SUBURB], $line[RTT_SUBURB]);

// if match, return true
}

});

$matches будет массив совпавших строк.

Это зависит от вашей структуры данных, но лучше использовать array_merge в сочетании с array_unique

1

Другие решения

Какой допуск вы использовали для алгоритма расстояния Левенштейна? По моему опыту, менее 0,8 вернуло бы слишком много ложных совпадений. В итоге я использовал ручные поправки для коротких слов, таких как raod = road, иначе оценка была бы неправильной на 1 символ, что соответствовало 75%. Я нашел статью для 12 тестов для поиска адресов с использованием нечеткого сопоставления это может быть полезно для улучшения вашего алгоритма. Примеры включают в себя:

  1. Орфографические ошибки
  2. Недостающее пространство
  3. Неверный тип (улица против дороги)
  4. Граница / пригород
  5. Сокращения
  6. Синонимы: этаж против уровня
  7. Единица, квартира или квартира против письма
  8. Число против буквы
  9. Дополнительные слова (например, входная дверь, название отдела)
  10. Поменялись буквами
  11. Звучит как
  12. Токенизация (другой порядок ввода
0

По вопросам рекламы [email protected]