php-resource




Archiv verlassen und diese Seite im Standarddesign anzeigen :
Unterschiede von Artikeln anzeigen


 
php_jan
06-12-2005, 11:18 
 
Ich möchte verschiedene Versionen von Artikeln abspeichern wie z.B. bei Wiki.

Beispiel:

Version1: Jetzt lerne ich PHP!
Version2: Jetzt lerne ich PHP und MySQL!

Wie kann ich mir den Unterschied, also z.B. von Version1 nach Version 2 anzeigen, dass "! und MySQL" angezeigt wird oder sogar nur der Unterschied farblich hervorgehoben wird.

Hier handelt es sich um ein sehr einfaches Beispiel. Die Artikel können mehrere Seiten lang werden und können beliebig editiert werden. Die verschiedenen Versionen lege ich in MySQL ab.
Gibt es da eine komfortable Lösung?

Freue mich über jede Hilfe, weil ich an dieser Stelle einfach nicht weiterkomme.

Gruß,
php_jan

 
onemorenerd
06-12-2005, 11:40 
 
Original geschrieben von php_jan
Gibt es da eine komfortable Lösung?Oh nein. Vollziehe nur mal folgendes Beispiel nach (nicht als Schreien gemeint):

Version1: Jetzt lerne ich PHP!
Version2: Jetzt lerne ich PHP!!

Sieht trivial aus, aber es stellen sich folgende Fragen:
Habe ich in Version2 ein ! hinten angehangen oder
habe ich ein ! vor das bereits vorhandene gesetzt oder
habe ich das alte ! gelöscht und zwei neue hingeschrieben?

Der letzte Teil ist vielleicht unwichtig, aber schon im ersten Oder dieser Frage steckt ein unlösbares Problem. Du mußt diesen Fall vorab entscheiden, z. B. sagst du "immer das letzte ! ist neu".

So weit so einfach. Nächstes Beispiel:

Version1: Jetzt lerne ich PHP!
Version2: Jetzt versuche ich PHP!
Version3: Jetzt versuche ich PHP zu lernen!
Version4: Jetzt mach mal einer Kaffee hier!

Frage: Was würdest du gern als Unterschied zwischen den Versionen ansehen und markieren? Einfach ein Stringmatching vom Start an soweit wie es eben möglich ist und der Rest muß neu sein? Sehr schlechte Idee, denn dann Füge ich vor einen ellenlangen Text ein einziges Wort und schon wäre für dich der ganze Text neu. Also gleich wieder weg mit dem Ansatz! Aber wie dann? Hast du dir da schon Gedanken gemacht?

Es gibt dutzende Alignment-Algorithmen, hauptsächlich aus der Bioinformatik, aber man kann einige auch ganz gut auf ein richtiges Alphabet (statt nur AGCT oder 23 Proteine) anwenden. Deren Komplexität ist allerdings extrem oder sie sind heuristisch (oder beides ;)).

Ganz so einfach ist es also wirklich nicht.

 
php_jan
06-12-2005, 11:51 
 
Version1: Jetzt lerne ich PHP!
Version2: Jetzt versuche ich PHP!
Version3: Jetzt versuche ich PHP zu lernen!
Version4: Jetzt mach mal einer Kaffee hier!

Frage: Was würdest du gern als Unterschied zwischen den Versionen ansehen und markieren?

Von Version1 nach Version2:

Jetzt versuche ich PHP!

Von Version2 nach Version 3:

Jetzt versuche ich PHP zu lernen!

Von Version3 nach Version 4:
Jetzt mach mal einer Kaffee hier!

Die Idee mit dem Stringmatching hatte ich auch, aber funktioniert nur, wenn ich einzelne Zeilen, wo sich etwas geändert hat, markieren möchte.

Das scheint wirklich nicht ganz so einfach zu sein. Werde mal nach Algorithmen suchen, von denen du gesprochen hast...

 
onemorenerd
06-12-2005, 12:17 
 
Von Version1 nach Version2:
Du: Jetzt versuche ich PHP!
Ich: Jetzt versuche ich PHP!

Von Version2 nach Version 3:
Du: Jetzt versuche ich PHP zu lernen!
Ich: Jetzt versuche ich PHP zu lernen!

Von Version3 nach Version 4:
Du: Jetzt mach mal einer Kaffee hier!
Ich: Jetzt mach mal einer Kaffee hier!

Man könnte es auch genauer betrachten:
Version3: Jetzt versuche ich PHP zu lernen!
Version4: Jetzt mach mal einer Kaffee hier!

... und das obwohl es ein ganz einfaches, dummes Beispiel ist und nur sichtbare Zeichen berücksichtigt wurden.

 
php_jan
06-12-2005, 12:28 
 
Hmmm ich hatte auch schon mal diese Idee...

ver.1 "Jetzt lerne ich PHP!"
ver.2 "Jetzt lerne ich nicht PHP!"

um den Unterschied zwischen Version 1 und Version 2 festzustellen...

- beide Artikel in zwei Arrays speichern:

$arrayVer1[0]="Jetzt"
$arrayVer1[1]="lerne"
$arrayVer1[2]="ich"
$arrayVer1[3]="PHP!"

$arrayVer2[0]="Jetzt"
$arrayVer2[1]="lerne"
$arrayVer2[2]="ich"
$arrayVer2[3]="nicht"
$arrayVer2[4]="PHP!"

Den Unterschied von Version 1 nach Version 2:

arrayVer1[0]==arrayVer2[0] -> sind gleich also nicht markieren
arrayVer1[1]==arrayVer2[1] -> sind gleich also nicht markieren
arrayVer1[2]==arrayVer2[2] -> sind gleich also nicht markieren
arrayVer1[3]==arrayVer2[3] -> nicht gleich also markiere "nicht"

Jetzt $arrayVer1[3]="PHP!" weiter im $arrayVer2 wenn gefunden, dann alles dazwischen markieren. Wenn es nicht gefunden wird, dann mit dem nächsten Element von $arrayVer1 weiter... Welches in diesem Beispiel nicht vorhanden ist....

 
php_jan
06-12-2005, 12:31 
 
Von Version1 nach Version2:
Du: Jetzt versuche ich PHP!
Ich: Jetzt versuche ich PHP!

Von Version2 nach Version 3:
Du: Jetzt versuche ich PHP zu lernen!
Ich: Jetzt versuche ich PHP zu lernen!

Von Version3 nach Version 4:
Du: Jetzt mach mal einer Kaffee hier!
Ich: Jetzt mach mal einer Kaffee hier!

Man könnte es auch genauer betrachten:
Version3: Jetzt versuche ich PHP zu lernen!
Version4: Jetzt mach mal einer Kaffee hier!

so genau brauch ich das nicht... die einzelnen Worte reichen mir aus...

 
php_jan
06-12-2005, 12:35 
 
und ich dachte schon, es gäbe eine triviale Lösung! Aber vielen Dank, dass du dir so viel Mühe gibst!
Werde natürlich posten, wenn ich etwas brauchbares gefunden habe...

 
onemorenerd
06-12-2005, 13:22 
 
Nunja es gibt eine ganz einfache Lösung, wenn du dich damit abfinden kannst, dass sie eben nicht so gut ist.

Das was du mit den Arrays angedeutet hast, entspricht prinzipiell dem gebräuchlisten Ansatz: Man hat zwei Strings und zwei Zeiger, die man sequentiell drüber schiebt und Zeichen für Zeichen vergleicht.
Stimmen die Zeichen nicht überein (case-sensitivity?), schiebt man beide Zeiger
a) bis zum Ende des Wortes
b) soweit, bis einer von beiden am Ende des Wortes ist
und markiert das Wort als Mismatch. Bei Variante B hat man evtl. in einem der beiden Strings noch den Rest des Wortes vor dem Zeiger und kann weitere Fallunterscheidungen machen. Das ist auch nötig, denn stell dir mal vor du hast

String A: Ich wäre gern ein langer Text.
String B: Ichwäre gern ein langer Text.

Deine Array-Methode würde die beiden ersten Wörter als verschieden erkennen, aber dann den Faden nicht wieder aufnehmen können. Sie würde nämlich 'wäre' mit 'gern', 'gern' mit 'ein' usw. vergleichen. Man könnte nun zwar implementieren, daß nach dem Wort 'wäre' in Array B gesucht wird, dann nach 'gern', das findet man und schon hat man den Faden wieder. Klingt logisch, hat aber Lücken: Was passiert, wenn das Wort 'wäre' später im Text noch einmal vorkommt? Wie sicherst du ab, dass du keinen 'falschen Faden' aufgreifst?

Dieses Problem ist mit dem Array-Ansatz schwer (überhaupt nicht?) zu lösen. Deswegen vergleicht man eigentlich zeichenweise.

Wie gesagt (uh, hab ich das schon gesagt?), ich empfehle dir, einen fertigen Algorithmus zu nehmen. Stichworte könnten diff, versioning und matching sein. Kannst ja auch mal bei http://koders.com schauen, ich hab da zumindest schon mal einige KMP-Implementierungen gesehen.

(KMP = Knuth-Morris-Pratt)

 
ghostgambler
06-12-2005, 17:30 
 
warum immer so umständlich?

Wikis-Diff-Engine im Anhang, aus einer der 1.5er-Versionen sogar (glaube ich)

Benutzung:

require_once(TAS_PATH . '/wiki_diff.inc.php');
$ota = explode( "\n", str_replace( "\r\n", "\n", $_POST['Artikel'] ) );
$nta = explode( "\n", str_replace( "\r\n", "\n", $Artikel->get_content() ) );
$diffs =& new Diff( $ota, $nta );
$formatter =& new TableDiffFormatter();
$difftext = $formatter->format( $diffs );
if (!empty($difftext)) {
echo '<table border=\'0\' width=\'98%\' cellpadding=\'0\' cellspacing=\'4\' class=\'diff\'>
<tr>
<td colspan=\'2\' width=\'50%\' align=\'center\' class=\'diff-otitle\'>' . $Artikel->get_Titel() . '</td>
<td colspan=\'2\' width=\'50%\' align=\'center\' class=\'diff-ntitle\'>' . $Artikel->get_Titel() . '</td>
</tr>';
echo $difftext . "</table>\n";
} else {
echo '<p>Keine &Auml;nderungen</p>';
} // if (!empty($difftext))

(ja, der Code hier ist spezifisch und funktioniert so nicht und ja ihr müsst da was dran ändern....aber das sollte wohl nicht das Problem sein *keine Lust dazu hat jetzt hier alles passend zu posten*)

 
php_jan
06-12-2005, 18:00 
 
Vielen Dank erstmal für eure Bemühungen! Es überrascht mich doch sehr, wievel Hilfe man hier bekommt, wenn man nicht weiter weiß.

Eine Frage hätte ich da auch noch ;-)
Darf ich die Datei von Wiki überhaupt so einbinden? Was muss ich da beachten? Aber dafür bin ich vielleicht auch schon im falschen Forum ;-)

 
ghostgambler
06-12-2005, 20:28 
 
ka ... opensource, solange du kein Geld damit machst, sollte das in Ordnung sein :D
btw. waren nur 2 Klicks, weil das Original-Code aus meinem Artikel-System ist ^^ (tja, an die Wiki-Diff-Engine kommt so schnell nichts ran, auch wenn ich sagen muss, dass meine Eigenproduktion zwar nicht so nett aussah, aber für grobe Änderungen durchaus reichte und nicht so fett war ^^,,,)


Alle Zeitangaben in WEZ +2. Es ist jetzt 18:13 Uhr.