Portal > Foren > PHP > PHP-Programmierung > NUR doppelte Werte aus einem Array anzeigen
Antwort
 
Themen-Optionen Thema durchsuchen
Alt 06.10.2008, 20:07 Nach oben    #1
neugieriger PHP-Anfäger
 
Registriert seit: 16.08.2008
Ort: Mecklenburg-Vorpommern
Beiträge: 45
Standard NUR doppelte Werte aus einem Array anzeigen

Hey,

die Frage steht eigentlich schon im Topic: Wie gebe ich die doppelten Werte in einem Array aus? Und nur die doppelten?

Danke!
Sekundentakt ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 06.10.2008, 22:22 Nach oben    #2
Johannes Schlichenmaier
 
Benutzerbild von Jojo
 
Registriert seit: 26.08.2005
Ort: Mannheim
Beiträge: 403
Standard

Unter der Vorraussetzung, dass a) du max. doppelte Einträge vorkommen (für mehr muss man das Konstrukt ein wenig modifizieren, wobei ich mir da garnicht mehr so sicher bin...) und b) du die doppelten Einträge dann nur einfach brauchst, also dein Endarray dann so aussieht:
Code:
array( [0] => "eins"
       [3] => "zwei"
       ...
        )
kann man deinen Wunsch recht einfach mit der Kaskadierung der beiden array-Funktionen array_diff_key() und array_unique() realisieren:

PHP-Code:
$array = array( "eins""zwei""zwei""drei""vier""vier""funf""funf");
$d_array array_diff_key($arrayarray_unique($array)); 
Ausgabe wäre dann:
Code:
Array
(
    [2] => zwei
    [5] => vier
    [7] => funf
)
Zumind. ist das ne schnelle Lösung, die mir grad einfällt. Eine direkte Funktion, die das Gegenteil von array_unique ausführt ist mir nicht bekannt.

EDIT:
Ich hab das mal eingefärbt!
Das stimmt leider nicht, meine Lösung, denn für array_diff spielt es keine Rolle, ob der Einträg mehrmals vorkommt. Das Ergebnis wird durchweg ein leeres Array sein. Tja, typischer Fall von nicht nachgedacht vor gepostet...


EDIT 2:
Ich hab ganz übersehn, dass array_unique() die Keys preserved.
Also funktioniert mein Konstrukt doch mit array_diff_key(). Hab meinen Beitrag mal dahingehend editiert.
__________________
In the beginning was the word
and the word was content-type: plain/text

heute code ich, morgen debug ich und uebermorgen cast ich die koenigin auf int

Geändert von Jojo (06.10.2008 um 22:57 Uhr)
Jojo ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 06.10.2008, 22:46 Nach oben    #3
neugieriger PHP-Anfäger
 
Registriert seit: 16.08.2008
Ort: Mecklenburg-Vorpommern
Beiträge: 45
Standard

Ich denke, dass array_unique alle doppelten Werte löscht? Das verstehe ich jetzt nicht. Hm...

Was möchte ich eigentlich machen? Lass mich mal konkreter werden:
Ich habe einen String, ausgelesen aus einer Datenbank und einen weiteren String.
Diese Strings werden in ihre einzelnen Worte zerschnitten. Am Ende habe ich zwei Arrays, dass erste mit Datenbankeinträgen, dass andere mit den Suchworten.
Jetzt möchte ich z.B. das (Datenbank)array[0] mit dem (Suchwort) array[3] durch eine Funktion vergleichen und stelle fest, die sind sich ähnlich. Nun speicher ich den Wert aus array[0] in einem Vorschlags-Array und kann am Ende ein paar Suchvorschläge präsentieren. Wie spielt sich das ab? Stell dir vor, dass das zweite Suchwort, und das dritte Suchwort auf ein und den selben Datenbankeintrag passen, dann habe ich sie also zwei mal in meinem Array mit Suchvorschlägen. Nun möchte ich, dass die Werte, die am häufigsten vorkommen, als erstes ausgegeben werden, dann die Vorschläge mit den nächst geringeren Treffern.

Ich hoffe, damit konnte ich ein wenig dabei helfen, mir zu helfen.

Danke!

P.S.
Ich weiß, dass es für die Suche in einer Datenbank auch andere Funktionen gibt, in DIESEM Fall, wäre diese Vorgehensweise (oder eine mit ähnlicher Wirkung) aber von großem Vorteil
Sekundentakt ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 06.10.2008, 23:06 Nach oben    #4
Johannes Schlichenmaier
 
Benutzerbild von Jojo
 
Registriert seit: 26.08.2005
Ort: Mannheim
Beiträge: 403
Standard

Also als erstes: Ich hab meinen ersten Beitrag mal editiert.
Der macht übrigens genau das, was du im Startpost definiert hast: Gibt dir alle doppelt vorkommenden Elemente eines Arrays zurück. Das array_unique() ist nur ein Hilfskonstrukt, um das zu erreichen. Entscheidend ist das array_diff_key()

Zu deiner Erklärung:
Sei mir nicht böse, kann auch an der Uhrzeit liegen, aber ich werd aus deiner Erklärung nicht wirklich schlau.

Es klingt ein wenig diffus... Möchtest du jetzt doppelte Einträge in einem Array ausgeben, oder möchtest du Wörter aus einer Benutzereingabe mit Keywörtern auf Ähnlichkeit überprüfen und diese dann noch nach Häufigkeit sortieren?
Das sind in meinen Augen zwei paar Schuhe.

Wenn du zur Zeit nur den obrigen Algoritmus brauchst, dann ist ja alles ok, andernfalls musst du deine Spezifikationen verfeinern.
Dazu ein Tipp: Wörtliche Spezifikationen sind für eine reale Code-Umsetzung nicht wirklich sinnvoll.
Versuch mal einen schematischen Ablauf (ein bisschen so wie in Mathe) zu erstellen.
Dann lässt sich darüber leichter diskutieren.

Grüße,
Jojo
__________________
In the beginning was the word
and the word was content-type: plain/text

heute code ich, morgen debug ich und uebermorgen cast ich die koenigin auf int
Jojo ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 07.10.2008, 07:27 Nach oben    #5
neugieriger PHP-Anfäger
 
Registriert seit: 16.08.2008
Ort: Mecklenburg-Vorpommern
Beiträge: 45
Standard

Ich werd aus der Unique-Sache von oben immer noch nicht schlau, sorry .
Ich habe mir die Definitionen schon zig mal durchgelesen, aber der Groschen will irgendwie nicht fallen.

Ein mathematischer Ablauf? Ich versuche es.

gegeben:
- Datenbankeinträge (z.B. Schlagworte bzw. Schlagwortketten)
- User-Suchstring

gesucht:
- die Schlagworte und Schlagwortketten (Ketten=mindestens zwei Worte), welche die größte Ähnlichkeit mit dem falsch geschriebenen Suchstring haben.

Ich könnte das Ganze natürlich in einer einzigen Funktion abarbeiten.
zum Beispiel mit der Levenshtein-Funktion.

Ich stelle mir das ganze so vor, dass die Schlagwortkette ausgelesen und in einem Array gespeichert wird.
Ein Arraykästchen wird dann in seine einzelnen Worte zerlegt und in einem weiteren Array gespeichert. DIESES Array gehe ich durch und vergleiche Wort für Wort, die Wahrscheinlichkeit, mit der es mit einem der falschgeschriebenen Suchworte übereinstimmt. Stimmt das Wort überein, wird der Arrayeintrag mit der kompletten Schlagwortkette gespeichert.
Nun könnte es ja möglich sein, dass ich eine Schlagwortkette mehrfach speichere, weil mehrere Suchworte Ähnlichkeiten mit mehreren Schlagworten einer Kette aufweisen.
Das Array, in das ich nun die Treffer gespeichert habe, soll mir die HÄUFIGSTEN Werte NUR einmal, ABER an erster Stelle, AUSGEBEN.

Jetzt vielleicht etwas klarer?

Ich habe einen möglichen Lösungsansatz entwickelt, allerdings scheint der nicht zu funktionieren, wie ich es mir vorstelle:

PHP-Code:
$i 1;
$k = array('hey''hallo''Hi''Na');
$k[$i]['shortest'] = 0;


echo 
$k[$i];
echo 
"<br>";
echo 
$k[$i]['shortest']; 
Die Ausgabe ist dann:
Zitat:
0allo
0
Was mache ich falsch?

EDIT: Ich hab jetzt eine andere Version genutzt. Mich würde aber trotzdem interessieren, wieso DAS da nicht geht?

Wenn ich ein Array habe von dieser Form:
$array[$n]['Wert']="Dies"
$array[$n]['Zähler']=5

und ich jetzt sage, dass $n=4 ist, dann habe ich 5 Array"Fächer".
Ich möchte das die Array WERTE nach den ZÄHLERN geordnet ausgegeben werden, wie realisiere ich DAS? Danke!

Geändert von Sekundentakt (07.10.2008 um 19:55 Uhr)
Sekundentakt ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 07.10.2008, 19:55 Nach oben    #6
neugieriger PHP-Anfäger
 
Registriert seit: 16.08.2008
Ort: Mecklenburg-Vorpommern
Beiträge: 45
Standard

sorry, doppelpost, s. oben

EDIT: Doch nicht
Sekundentakt ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 08.10.2008, 19:06 Nach oben    #7
Johannes Schlichenmaier
 
Benutzerbild von Jojo
 
Registriert seit: 26.08.2005
Ort: Mannheim
Beiträge: 403
Standard

Hallo,

sry dass ich mich jetzt erst wieder melde, aber ich hab grad recht viel um die Ohren.

Zitat:
Zitat von Sekundentakt Beitrag anzeigen
PHP-Code:
$i 1;
$k = array('hey''hallo''Hi''Na');
$k[$i]['shortest'] = 0;


echo 
$k[$i];
echo 
"<br>";
echo 
$k[$i]['shortest']; 
Die Ausgabe ist dann:
Zitat:
0allo
0
Was mache ich falsch?
Nun, ich weiß nicht, was genau du machen möchtest, aber der Code setzt ja nur $k[1]['shortest'] auf "0".
PHP interpretiert seinerseits den String, der vorher in $k[1] gespeichert war als Char-Array und da 'shortest' kein numerisches Zeichen ist, ersetzt es den ersten Charakter.
Dann wird einfach $k[i] und $k['shortest'] ausgegeben.


Zitat:
Zitat von Sekundentakt Beitrag anzeigen
und ich jetzt sage, dass $n=4 ist, dann habe ich 5 Array"Fächer".
Ich möchte das die Array WERTE nach den ZÄHLERN geordnet ausgegeben werden, wie realisiere ich DAS? Danke!
Das geht wiederum wunderbar mit array_multi_sort().
Beispiel 3 erklärt, wie es grundsätzlich in deinem Fall läuft.

Grüße,
Johannes

PS:
Nochmal kurz zu dem array_unique-Part da oben:
array_unique() gibt dir ein Array zurück, wobei alle doppelten Einträge entfernt sind.
Wenn mein Ausgangsarray so aussieht:

Code:
Array
(
    [0] => eins
    [1] => zwei
    [2] => zwei
    [3] => drei
    [4] => vier
    [5] => vier
    [6] => funf
    [7] => funf
)
Dann lautet die Rückgabe von array_unique($array) also:
Code:
Array
(
    [0] => eins
    [1] => zwei
    [3] => drei
    [4] => vier
    [6] => funf
)
Man beachte, dass die Keys nicht durchgängig sind, sie bleiben erhalten, wobei array_unique bei gleichen Feldern immer das erste behält.

So, array_diff_key() vergleicht zwei Arrays gegeneinander und gibt die Felder aus, bei denen sich keys unterscheiden.

Ein
PHP-Code:
$d_array array_diff_key($arrayarray_unique($array)); 
macht also nichts anderes, als die Elemente mit den Keys, die sich im bereinigten Array von denen im Arsprungsarray unterscheiden (auch ein Nichtvorhandensein wird als Unterschied behandelt) zurückzugeben.

Die Funktion sieht also die beiden Arrays und sagt: Ok, beide Arrays haben einen Key 0, 1, 3, 4 und 6. Einen Key 2, 5 und 7 hat also lediglich das Ursprungsarray.
Dies sind aber genau jenen, die die Funktion array_unique wegen doppeltem Vorkommen herausgefiltert hat.
Du hast mit anderen Worten als Endergebnis die Elemente des Ursprungsarrays, die die Funktion array_unique vorher rausgelöscht hat.
Die doppelten Einträge also.

PPS:
Falls das deine Schwierigkeit sein sollte:
Wie die meisten PHP-Funktionen verändert array_unique() keine übergebenen Parameter. Nur die Rückgabe ist ein von Mehrfacheinträgen gesäubertes Array.
__________________
In the beginning was the word
and the word was content-type: plain/text

heute code ich, morgen debug ich und uebermorgen cast ich die koenigin auf int

Geändert von Jojo (08.10.2008 um 22:01 Uhr)
Jojo ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 09.10.2008, 00:30 Nach oben    #8
Johannes Müller
 
Benutzerbild von $traight-$hoota
 
Registriert seit: 15.09.2005
Ort: Königreich Flieden
Beiträge: 550
Standard

Also mir wird letzlich nicht klar, was für einen Algorithmus du jetzt eigentlich realisieren willst...

Also du hast eine Suchanfrage vom User und (aus der Datenbank) ein Reportaire verschiedener Suchvorschläge. Als Beispiel nehme ich dafür einfach mal "rote tomate", "was ganz dolles" und "telefon".
Diese Vorschläge werden in einzelne Worte aufgespalten (per explode) und in einem zweidimensionalen Array gespeichert.
PHP-Code:
$data = array(
    array(
"rote""tomate"),
    array(
"hallo""oma"),
    array(
"was""ganz""dolles"),
    array(
"telefon")
); 
Das sind dann die Daten von denen das ganze Ausgeht.
Ebenso wird auch die Suchanfrage nach Worten aufgeteilt.
PHP-Code:
$suche = array("das""telefon""sagt""was""dolles"); 
In Pseudocode ausgedrückt, verstehe ich aus deiner Beschreibung folgendes:
Code:
FUNCTION algo($data, $suche)
    FOR $suchvorschlag IN $data
        FOR $wort IN $suchvorschlag
            FOR $suchwort IN $suche
                IF vergleiche($suchwort, $wort)
                    habGefunden($suchvorschlag)
END
In PHP umgesetzt ist das natürlich noch ein bischen mehr, aber das dient so nur zum groben Verständnis, was der Algorithmus machen soll.
Die Funktion vergleiche arbeitet also mit levensthein oder was auch immer, und liefert ein ergebnis, ob die worte gleich sind oder nicht. Da könnte auch ne gewisse näherung eingebaut werden, dass auch ne 95% Übereinstimmung true zurückgibt, aber das ist jetzt grade egal.
Die Funktion habGefunden sammelt alle Suchvorschläge und zählt mit, wie oft jeder gefunden wurde.

In PHP könnte das so aussehen:
PHP-Code:
$gefunden = array();
function 
gefunden($suchvorschlag) {
    global 
$gefunden;
    if(! 
array_key_exists($gefunden$suchvorschlag)) {
        
$gefunden[$suchvorschlag] = 0;
    }
    
$gefunden[$suchvorschlag]++;

Am besten wird hier, nicht wie im Pseudeocode angedeutet das ganze Array übergeben, sondern der Arraykey des Suchvorschlags (das wäre nur oben zu kompiziert auszudrücken).
Am Ende hat man bei obigen Beispieldaten in $gefunden folgendes stehen:
PHP-Code:
array(
    
=> 1,
    
=> 2
); 
Da müssen nur noch key und value vertauscht und das array sortiert werden, dann hat man in absteigender folge die ids der suchstrings mit den meisten übereinstimmungen.
Code:
übereinstimmungen | suchvorschlag
------------------|--------------------------
                2 | 2 => "was ganz dolles"
                1 | 3 => "telefon"
ist das jetzt das, was du willst??
__________________
Weißt Bescheid - Scheiß wie weit

Geändert von $traight-$hoota (09.10.2008 um 00:35 Uhr)
$traight-$hoota ist gerade online  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 09.10.2008, 21:26 Nach oben    #9
neugieriger PHP-Anfäger
 
Registriert seit: 16.08.2008
Ort: Mecklenburg-Vorpommern
Beiträge: 45
Standard

Hi,

nein, ist es nicht. Ich bin leider von einem völlig falschen Lösungsansatz ausgegangen. Arrays sind für das, was ich möchte, völlig falsch.
Ich habe mir dann tatsächlich mal das levenshtein-Funktions-Beispiel von php.net genommen und modifziert. Ich erreiche genau das, was ich vorher von euch wollte, indem ich die Treffer in eine Variable speichere. Würde ich statt einer Variable ein Array verwenden, würde das den Code am Ende aufblasen, ohne einen wirklichen Mehrwert zu bringen, da viele Arrayfelder einfach leer bleiben würden.
Eine Variable reicht völlig aus, wer mehr Suchvorschläge braucht, muss das Konstrukt, wie ich, modifizieren - mit Variablen.

Levenshtein-Funktion

Danke aber für eure Hilfe!
Sekundentakt ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 09.10.2008, 21:36 Nach oben    #10
Johannes Schlichenmaier
 
Benutzerbild von Jojo
 
Registriert seit: 26.08.2005
Ort: Mannheim
Beiträge: 403
Standard

Zitat:
Zitat von Sekundentakt Beitrag anzeigen
nein, ist es nicht. Ich bin leider von einem völlig falschen Lösungsansatz ausgegangen. Arrays sind für das, was ich möchte, völlig falsch.
Insgeheim hab ich auch vermutet, dass du bezüglich der Funktionsweise von Arrays in PHP was anderes im Kopf hattest
Allerdings hab ich den Mund gehalten, weil mir nicht ganz klar war, wie dein Alorithmus später mal arbeiten sollte...
Aber gut, dass das geklärt ist.
Kannst ja, wenn du noch lustich bist, dein Endergebnis hier präsentieren.
Dann haben andere vielleicht auch noch was davon...


Grüße,
Jojo
__________________
In the beginning was the word
and the word was content-type: plain/text

heute code ich, morgen debug ich und uebermorgen cast ich die koenigin auf int
Jojo ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 09.10.2008, 22:21 Nach oben    #11
neugieriger PHP-Anfäger
 
Registriert seit: 16.08.2008
Ort: Mecklenburg-Vorpommern
Beiträge: 45
Standard

Hier mal das, was meine Funktion macht.
Ich betone, dass ich das im obrigen Link enthaltene Beispiel lediglich modifiziert habe.

PHP-Code:
      // berechne die Distanz zwischen Inputwort und aktuellem Wort
          
$lev levenshtein($input$word);

               
// auf einen exakten Treffer prüfen
            
if ($lev == 0) {
                
                  
// das nächste Wort ist das Wort selbst (exakter Treffer)
                  
$Höchster_Treffer $words;
                  
$shortest 0;
                  
// Schleife beenden, da wir einen exakten Treffer gefunden haben
                  
$stop TRUE;
                break;
               }

          
// Wenn die Distanz kleiner ist als die nächste gefundene kleinste Distanz
          // ODER wenn ein nächstkleineres Wort noch nicht gefunden wurde
          
if ($stop === FALSE) {
            
              if (
$lev <= $shortest || $shortest 0) {
               
// setze den nächstliegenden Treffer und die kürzestes Distanz
             
$Höchster_Treffer  $words;
               
$shortest $lev;
               
              
//Wenn $lev größer als $shortest (das alte $lev) ist, aber nicht mehr als drei mal häufiger
              //verändert werden muss, dann setze ich $Zweithöchster_Treffer = dem aktuellen $words
              
} elseif ($lev $shortest and $lev $shortest+3) {

                  
$Zweithöchster_Treffer $words;
                  
$shortest2 $lev;
      
              
//ähnlich wie für den zweithöchsten Treffer, nur dass der dritthöchste nicht mehr als
              //drei Zeichen häufiger verändert werden muss, als beim zweithöchsten Treffer ODER,
              //einfacher ausgedrückt, der dritthöchste Treffer darf maximal 3x häufiger verändert werden
              //als der höchste Treffer
             
} elseif ($lev $shortest2 and $lev $shortest2+3) {
                  
                
$Dritthöchster_Treffer $words;
                  
$shortest3 $lev;
              }
          } else {
              break;
          } 
Jetzt zeige ich euch einfach mal den gesamten Code, natürlich stark vereinfacht (bevor ich versuche über diese Funktion einen Suchvorschlag zu ermitteln, wandert der Suchstring nämlich bereits durch eine recht gründliche Suchfunktion.
Genau genommen, würde diese Funktion eigentlich nur zum Einsatz kommen, wenn ALLE Suchbegriffe in irgendeiner Form falsch geschrieben wurden oder absolut nicht in meiner Datenbank auftauchen.

Hier das komplette Codebeispiel:

PHP-Code:
$Daten[0] = "Satz des Pytagoras||Funktionen||mathematische Grundlagen||Mathematik (Funktion)";
$Daten[1] = "Marmelade||Zitronensaft||Mathematik";

$Suchstring "Saz dis Pütaguras";
$Suchworte explode(" "$Suchstring);

$i 0;
$stop FALSE;
$shortest=-1;

while (
$Datensatz_Aktuell $Daten[$i]) {
    
    
$Datensätze explode("||"$Datensatz_Aktuell);
    
$Datenworte = array();

        
$l=0;
        
    foreach (
$Datensätze as $words) {
    
        
        
$Datenworte    explode (" "$words);
        
      foreach(
$Datenworte as $word){
        
      foreach (
$Suchworte as $input) {
        
    
          
// berechne die Distanz zwischen Inputwort und aktuellem Wort
          
$lev levenshtein($input$word);

               
// auf einen exakten Treffer prüfen
            
if ($lev == 0) {
                
                  
// das nächste Wort ist das Wort selbst (exakter Treffer)
                  
$Höchster_Treffer $words;
                  
$shortest 0;
                  
// Schleife beenden, da wir einen exakten Treffer gefunden haben
                  
$stop TRUE;
                break;
               }

          
// Wenn die Distanz kleiner ist als die nächste gefundene kleinste Distanz
          // ODER wenn ein nächstkleineres Wort noch nicht gefunden wurde
          
if ($stop === FALSE) {
            
              if (
$lev <= $shortest || $shortest 0) {
               
// setze den nächstliegenden Treffer und die kürzestes Distanz
             
$Höchster_Treffer  $words;
               
$shortest $lev;
               
              
//Wenn $lev größer als $shortest (das alte $lev) ist, aber nicht mehr als drei mal häufiger
              //verändert werden muss, dann setze ich $Zweithöchster_Treffer = dem aktuellen $words
              
} elseif ($lev $shortest and $lev $shortest+3) {

                  
$Zweithöchster_Treffer $words;
                  
$shortest2 $lev;
      
              
//ähnlich wie für den zweithöchsten Treffer, nur dass der dritthöchste nicht mehr als
              //drei Zeichen häufiger verändert werden muss, als beim zweithöchsten Treffer ODER,
              //einfacher ausgedrückt, der dritthöchste Treffer darf maximal 3x häufiger verändert werden
              //als der höchste Treffer
             
} elseif ($lev $shortest2 and $lev $shortest2+3) {
                  
                
$Dritthöchster_Treffer $words;
                  
$shortest3 $lev;
              }
          } else {
              break;
          }

                  } 
// Ende foreach 3
          
}    // Ende foreach 2
          
$l++;     
     } 
// Ende foreach 1
 
$i++;    
}    
// Ende while

if (empty($Höchster_Treffer)) 
    {
    echo 
"<p>Leider ergab deine Suche keinen Treffer</p>";
    
    } else {
        
$Treffer $Höchster_Treffer."<br>";
    } if (!empty(
$Zweithöchster_Treffer)) {
        
$Treffer $Treffer."<br>".$Zweithöchster_Treffer;
    } if (!empty(
$Dritthöchster_Treffer)) {
        
$Treffer $Treffer."<br>".$Dritthöchster_Treffer;
    }
    
if (!empty(
$Höchster_Treffer)) {
    echo 
"<p>".$Treffer."</p>";

Im Nachhinein würde es sich wohl in den meisten Fällen anbieten, eine Überprüfung via similar_text; durchzuziehen, da Levenshtein lediglich misst, wie häufig, in diesem Beispiel, der Suchstring angepasst werden müsste, um auf das aktuelle Schlagwort zu passen. Dadurch könnte man also vielleicht nach "Zitroneensaft" suchen, aber "Mathematik" als 2. Vorschlag zurückgeliefert bekommen.

*Schlagworte:
Schlagworte sind eigens in einer Datenbank gespeichert. Jeder Datensatz kann mehr als ein Schlagwort oder eine Schlagwortkette enthalten, diese werden, um voneinander unterschieden werden zu können, mit "||" im obrigen Beispiel getrennt. Schlagwortketten sind z.B. "Satz des Pytagoras". Sollte eine Schlagwortkette der Fall sein, zerschneide ich die Schlagwortkette.
Dann vergleiche ich Wort für Wort Suchworte und Schlagwortketten. Sollte EINES von mehreren Suchworten mit EINEM Schlagwort der Schlagwortkette übereinstimmen, so wird als Suchvorschlag die ganze SCHLAGWORTKETTE ausgegeben.

Anregungen:
Es kam bei diesem Codeschnipsel beim Testen durchaus vor, dass ich zwei mal den Selben Suchvorschlag ausgegeben bekomme. Das liegt daran, dass, sollte ein NEUER höchster Treffer gefunden werden, der alte höchste Treffer nicht zwangsläufig nachrutscht.
Wie gesagt, hierfür müsste man die Funktion erweitern, ggf. doppelte Vorschläge entfernen usw. usf.
Ich muss allerdings hinzufügen, dass es mir bei Datensätzen von mehr als 100 Einträgen noch nicht vorgekommen ist, dass zwei mal der selbe Suchvorschlag auftaucht. Bei weniger Datensätzen schon eher
Sekundentakt ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 09.10.2008, 23:45 Nach oben    #12
Johannes Müller
 
Benutzerbild von $traight-$hoota
 
Registriert seit: 15.09.2005
Ort: Königreich Flieden
Beiträge: 550
Standard

Ok, jetzt verstehe ich auch richtig, worum es bei dir geht^^

Ich würde dir (neben anderen Optimierungsmöglichkeiten*g*) aber trotzdem empfehlen, statt $shortest, $shortest2 und $shortest3 ein array zum abspeichern zu nehmen, da du dadurch felxibler bist und keine unnnötige Codedopplungen hast. Denn der Code für das Zuweisen und Ausgeben dieser drei variablen ist jedesmal vom Prinzip her identisch. Und wenn du dir irgendwann überlegst (warum auch immer), mehr vorschläge anbieten zu wollen, ist das durch eine einzige Variablenänderung geschehen; ebenso ist es einfacher, wenn der Code noch irgendwelche Veränderungen unterlaufen sollte (bugfixes, features...), diese nur einmal durchführen zu müssen.
Du meintest in deinem vorletzten Post, dass ein Array den Code unnötig aufblasen würde: das ist falsch und genau das Gegenteil der Fall. Was durch ein Array auf den ersten Blick sein kann, ist, dass das Datenvolumen erhöht wird (bei einer großen Datenbank), aber es gibt auch Möglichkeiten, das zu verhindern.
Beispielsweise musst du in $Höchster_Treffer etc. nicht den kompletten Datensatz speichern, sondern es würde reichen, eine Referenz von $words (&$words) oder einen eindeutigen Key zu übergeben (z.B. $i und ein hinzuzufügender Zähler im ersten foreach).
Alternativ kann das array auch per garbage collector auf eine beliebige Anzahl der jeweils höchsten Einträge begrenzt werden.
__________________
Weißt Bescheid - Scheiß wie weit
$traight-$hoota ist gerade online  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 10.10.2008, 00:17 Nach oben    #13
neugieriger PHP-Anfäger
 
Registriert seit: 16.08.2008
Ort: Mecklenburg-Vorpommern
Beiträge: 45
Standard

Könntest du den Code mal bitte dahingehend optimieren, dass das Ganze auch mit Arrays läuft? Jedesmal, wenn ich das versuche umzusetzen, zählt irgendetwas falsch hoch und er gibt das Falsche aus, bzw. auf einmal hat die längste Schlagwortkette die höchste Trefferzahl.

Danke!

EDIT:
Ich meinte mit dem Array-Problem, dass am Ende entweder immer nur die erste Schlagwortkette des Datensatzes steht, oder auf einmal alle Schlagworte als Vorschläge in Frage kämen.
Sekundentakt ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 10.10.2008, 03:45 Nach oben    #14
Johannes Müller
 
Benutzerbild von $traight-$hoota
 
Registriert seit: 15.09.2005
Ort: Königreich Flieden
Beiträge: 550
Standard

ganz am anfang müsste ein array $treffer initialisiert werden, $Höchster_Treffer, $Zweithöchster_ ... und $shortest ... entfallen.
Der gesamte Abschnitt nach der levensthein-berechnung kann eigentlich entfallen; stattdessen, werden mit diesem Code, alle Ergebnisse in einer Tabelle gesammelt, mit der dann hinterher weitergearbeitet werden kann.
PHP-Code:
if(!array_key_exists($treffer$words) || $treffer[$words] > $lev)) {
    
$treffer[$words] = $lev;

Damit wird zunächst überprüft, ob schon ein Wert durch ein anderes Wort des Eintrags existiert und ob dieser größer ist als der berechnete, sofern keiner existiert ode größer ist, wird das Ergebnis hinzugefügt.

Die Ausgabe erfolgt dann so:
PHP-Code:
// vorher: words => lev; nachher: lev => $words
$treffer array_flip($treffer);
// und jetzt nach levensthein-ergebnis sortieren
$treffer sort($treffer)
if(
array_key_exists($treffer0)) {
    
// Wir haben einen direkten Treffer mit $lev = 0;
    
echo "<p>".$treffer[0]."</p>";
} else {
    echo 
"<p>Leider ergab deine Suche keinen Treffer</p>";
    if(
count($treffer 0)) {
        
// jetzt gehts los, wir haben einen oder mehrere vorschläge
        
echo "<strong>Vorschläge:</strong>";
        
// array_slice verkleiner das array auf die drei höchsten drei Elemente
        
$treffer array_slice($treffer03);
        echo 
"<ol>";
        foreach(
$treffer as $lev => $words) {
             echo 
"<li>" $words "</li>";
        }
        echo 
"</ol>";
    }
}
unset(
$treffer); 
Dabei habe ich jedoch noch nicht berücksichtigt, dass du in deinem Quellcode noch beschränkt hast, dass ein Vorschlag maximal 3 Umformungen mehr haben darf als der vorherige.
Aber das ist in der foreach-Schleife der Ausgabe relativ einfach umsetzbar.
__________________
Weißt Bescheid - Scheiß wie weit
$traight-$hoota ist gerade online  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 10.10.2008, 15:54 Nach oben    #15
neugieriger PHP-Anfäger
 
Registriert seit: 16.08.2008
Ort: Mecklenburg-Vorpommern
Beiträge: 45
Standard

Ein paar Fragen zum Code:

Damit deine Rechnung aufgeht, muss ich array_flip(); anwenden, da ansonsten keine $words ausgegeben werden würden, sondern Zahlenwerte, ist das richtig? Wann greift denn array_flip();, bei einer Ausgabe? Oder werden die Werte automatisch nach dem abspeichern vertauscht? Versuch bitte diese Funktion mal an diesem Beispiel etwas genauer zu erklären, dass leuchtet mir noch nicht ganz ein, wieso das so funktioniert (woher weiß array_flip(); wann "nachher" ist?).

levenshtein hast du falsch verstanden, es muss nicht

$treffer[$words] > $lev, sondern $treffer[$words] < $lev heißen.

dein array_sclice(); ist dann glaube ich auch falsch, denn jetzt würde er zwar die ersten drei Treffer ausgeben, aber genau die sind doch die ungenauesten von allen? Du müsstest, wenn ich die Funktion richtig interpretiere, -3 angeben, damit ich die drei letzten Elemente des Arrays erhalte, da diese am genauesten sind, weil $lev am kleinsten war. Richtig?

Ich könnte das was $shortest+3 gemacht hat, theoretisch auch entfallen lassen, wenn meine letzten 3 Ergebnisse vor der Ausgabe noch durch ein similar_text(); gejagt werden und ich dann nur die Werte speichere, die dem Suchstring am ähnlichsten sind.

Danke für das Beispiel.
Sekundentakt ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!