Сопоставление массивов по значениям

#php #algorithm

#php #алгоритм

Вопрос:

У меня есть несколько записей во временной таблице в базе данных, и мне нужно объединить их, чтобы создать постоянные записи. Теперь информация поступает из нескольких XML-каналов, и у меня есть всевозможная информация, но самое близкое, что у меня есть, это «заголовок» или, в моем случае, название продукта. К сожалению, у меня нет другого способа (без одинаковых идентификаторов или чего-то подобного), кроме как сопоставлять их по имени. Так, например, у меня есть:

 $primary = array('feedid' => 2, 'entry_name' => 'ACME Product Black Model #23');
$secondary = array('feedid' => 3, 'entry_name' => 'ACME Product Model #23');
  

Продукт ACME может отличаться от "ACME Product Model #23" to "Model 23" , до « Black Model #23" и т.д.
Кроме того, в том же канале у меня может быть "ACME Product Model Black #22" и « CHOAM Product Black - Model 11" .

Проблема в том, что я не могу просто использовать similar_text() или levenshtein() , потому что они иногда соответствуют неправильным элементам, а иногда просто не совпадают вообще. Каждый канал содержит более 100 записей, и у меня может быть до 10 каналов.

Редактировать: чтобы выразить в реальных терминах, например: «iPhone 4» и «iPhone 4 White» и «iPhone 4 Black» должны быть объединены (я могу справиться со слиянием, сначала нужно сопоставить). Итак, правила таковы — сопоставьте телефоны в этом случае. Это также может быть «Белые волосы куклы Барби» и «Черные волосы куклы Барби», но не «Какая-то другая кукла с белыми волосами». …

Любые идеи приветствуются 🙂

Комментарии:

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

2. @Melsi Не уверен, что вы подразумеваете под простым английским. Проблема с сопоставлением заключается в том, что даже я не могу знать, какие каналы будут точно соответствовать. Я точно знаю, что у всех них будет название продукта. Как будет выглядеть имя, я не могу знать наверняка. Я должен выяснить, как работать с этими динамическими данными и корректно сопоставлять, насколько это возможно.

3. Несколько вопросов по этому поводу: Сможет ли человек это сделать? Если да, то какую информацию он будет использовать? Учитывая четыре примера, которые вы показали, я бы не смог определить, какие из них принадлежат друг другу, просто взглянув на заголовок. Итак, если кто-то способен это сделать, этому человеку, вероятно, требуются дополнительные правила, которые вы здесь не даете. Если человек не в состоянии это сделать, то о том, чтобы делать это автоматически, не может быть и речи полностью. Компьютеры лучше, чем люди, обрабатывают большие данные, но хуже справляются с задачами, требующими понимания или когнитивных способностей (как эта).

4. @LiKao , почему у вас возникли трудности с пониманием того, что «Продукт ACME № 23» — это то же самое, что «Продукт № 23 Black». Например, в реальных терминах: «iPhone 4» и «iPhone 4 White» и «iPhone 4 Black» должны быть объединены (я могу справиться со слиянием, сначала нужно сопоставить). Итак, правила таковы — сопоставьте телефоны в этом случае. Это также может быть «Белые волосы куклы Барби» и «Черные волосы куклы Барби», но не «Какая-то другая кукла с белыми волосами». … Но я понимаю вашу точку зрения в некотором смысле.

5. @Methmer: Потому что непонятно, что важно в заголовках. Например, у ACME может быть просто другая версия и только один продукт, поэтому «Модель продукта ACME # 23» и «Модель продукта ACME Black # 22» на самом деле могут быть одинаковыми. Я не знаю домен, поэтому не могу сказать. «Модель 23» с другой стороны, может относиться к чему-то совершенно другому. Если бы кто-нибудь дал мне только эту информацию, я бы сначала спросил их о компании, которая произвела это, чтобы убедиться. Без детального знания предметной области эта задача невозможна. Но это знание предметной области трудно закодировать.

Ответ №1:

В комментарии вы написали:

Я не могу знать, какие каналы будут точно соответствовать

Ну, если вы не можете сказать, как кто-нибудь другой должен вам сказать?

Прежде всего вам нужно решить вашу базовую проблему (получить номер модели из строки), чтобы продолжить.

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

Вы можете более или менее легко анализировать строки с помощью регулярных выражений:

 $r = preg_match('/Model(?: w )? #?(d )$/', $string, $matches);
if (!$r) throw new Exception(sprintf('Unable to parse "%s"', $string));
$modelNumber = $matches[1];
  

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

Комментарии:

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

2. @Methemer: Регулярные выражения на самом деле могут быть одним из методов кодирования знаний конкретной области. Если вы знаете ключевые слова, которые импортируются для имен ваших моделей, вы можете использовать регулярные выражения для извлечения этого. Также, если вы знаете информацию, которая всегда актуальна, то регулярные выражения могут помочь вам избавиться от них. В вашем примере, например, вы всегда можете попытаться удалить «ACME Product» и получить номер после «#» или в конце. Это позволило бы улучшить сопоставление, но все равно у вас будут ложные срабатывания, а также ложные отрицания.

Ответ №2:

Я думаю, что стоит использовать предварительное соответствие, которое предлагает хакре.

Я бы поступил так:

  1. (Необязательно) В старой временной таблице было бы добавлено еще одно поле tinyint, называемое flag.

  2. Я бы выбрал pregmatch, и в случае успешного предварительного сопоставления я бы поставил положительный флаг в старой таблице, чтобы указать, что эта запись была успешно обработана pregmatch.

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

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

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

Тогда, что касается извлечения новых данных, я бы выбрал сходство с текстом, например, что-то вроде mysql, например ‘%string%’.

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