2016-10-25 3 views
2

Ich muss anders strukturierte XML-Dateien mit PHP kombinieren. Was ich tue ist;Kombinieren Sie XML-Dateien basierend auf der Ähnlichkeit des Eintrags

  1. erste XML-Datei lesen simplexml_load_file()
  2. Reformieren die Elemente eine neue Struktur mit SimpleXMLElement() Klasse
  3. Machen Sie dasselbe für die andere Datei verwenden, Erhöhen der erste SimpleXMLElement() Instanz
  4. Speichern Sie die neu kombiniert XML-Datei .

So weit so gut. Der schwierige Teil ist, erste Datei hat ca. 3000 Einträge und die zweite Datei hat 5000. Fast 2000 dieser Einträge sind eigentlich gleich; vielleicht unterscheiden sich ein paar Buchstaben. Wie zum Beispiel; "Lenovo G50-70 CoreI5" und die andere könnte "Lenovo G5070 I5" sein.

Die Frage ist, wie kann ich einen Eintrag der ersten Datei mit dem gleichen Eintrag der zweiten Datei übereinstimmen; so dass es eigentlich nur einen Eintrag in der neuen kombinierten Datei gibt?

Ich benutze beide similar_text() Funktion von PHP und SmithWatermanGotoh, um Ähnlichkeit zu berechnen, und es matches mit einem Ergebnis von 86%; Das ist genug für mich. Aber das Iterieren aller Einträge der anderen Datei, um nur einem Eintrag zu entsprechen, ist für mich ziemlich unklug und ressourcenintensiv. Beucase bedeutet ca. 7MBs Datei in den Speicher geladen, die jedes Mal, wenn ich eine neue aktualisierte Datei speichere, mindestens 15.000 Iterationen durchführe.

Ich überlege, alle Einträge in eine Datenbanktabelle einzufügen und Sphinx Search zu verwenden, um Einträge zu finden; aber ich bin mir nicht sicher, ob es wirklich genug hilft.

+1

Wenn Speicher ein Problem ist, können [Generatoren] (http://php.net/manual/ro/language.generators.overview.php) helfen. – Andrew

+1

Ich denke, das Hauptproblem ist die Komplexität von 'ashite_text()'. Wenn ich Sie wäre, würde ich eine Reihe von Regeln definieren, um jeden Eintrag auf eine einzigartige Weise zu formatieren, dann können Sie die Duplikate leicht finden. –

+1

@CasimiretHippolyte, ich könnte Ihren Vorschlag nicht klar üben, würden Sie bitte genauer? Übrigens, es gibt genau dieselben Einträge, auch Duplikate genannt; aber es gibt auch Einträge, die gleiche, aber nicht exakte Duplikate sind. Wie das angegebene Beispiel in der Frage. – Turab

Antwort

1

Der beste Ansatz, den ich sehen konnte, ist die Verwendung eines benutzerdefinierten Rückrufs mit array_uintersect() Funktion. Dieser Weg funktioniert in Schritten wie;

1- Schreiben Sie eine Vergleichsfunktion, die die Ähnlichkeit berechnet. Überprüfen Sie array_uintersect() Handbuch von php.net, um eine Idee zu haben, wie Sie diese Callback-Funktion schreiben müssen. Say it's name wäre find_similar_entries()

2- Sammeln Sie beide Einträge aus verschiedenen XML-Dateien in zwei Arrays. (Für einen schnellen Weg, tun Sie zuerst eine json_encode() und dann json_decode() zurück.)

3- Haben Sie Schnittpunktfunktion finden Sie die ähnlichen Einträge wie; $similar_products = array_uintersect($xml_array1, $xml_array2, 'find_similar_entries');

4- Jetzt haben Sie ähnliche Einträge in einem Array gesammelt.

5- Rufen Sie array_diff(), um ähnliche Einträge aus den ursprünglichen Arrays zu entfernen.

6 - Schließlich kombinieren Sie alle drei Arrays in eine neue XML-Struktur je nach Wunsch, mit SimpleXMLElement() Klasse.

Anmerkung1: Ich habe similar_text() und SmithWatermanGotoh verwendet, um die Ähnlichkeit zu berechnen, und sie funktionieren gut zusammen, kann ich sagen. Aber wenn es um sehr enge Produktnamen geht, die sich nur um ein paar Zeichen voneinander unterscheiden, würden sie "identisch" sein. Sie können nichts dagegen tun, als die Unterscheidungswörter aus den Strings zu extrahieren. Wie "Modellname" in meinem Fall.

Anmerkung2: Diese Methode funktioniert wie erwartet, aber die Intersektionsfunktionen von PHP haben einen Bug, der diese Funktion so langsam macht. Ich habe dafür a bug report erstellt. Schnittpunkt vergleicht nicht die Elemente von zwei Arrays nur kreuzweise; aber es vergleicht auch die eigenen Elemente des Arrays. Dies ist eigentlich unlogisch, weil die Schnittmenge nur durch Vergleich von mindestens zwei Parteien berechnet werden kann. Ein Array von innen zu vergleichen, ist also kein "Schnittpunkt". Wenn Sie große Dateien haben, wird Ihr Skript daher abstürzen, wenn Sie es einfach ausführen. Vielleicht können Sie es Stück für Stück tun.

Verwandte Themen