devian: Werte gruppieren anhand von einem gemeinsamen Wert

Hallo liebe Selfhtml-Community,
ich habe ein kleines Problem, welches auf anhieb vl einfach aussieht aber es glaube ich nicht ist. Vorweg: Ich will kein einfaches Gruppieren!

Ich habe ein Forum wo jeder Beitrag mit einer Userid und einer IP Adresse gespeichert wird. Da ich mit gefakten Usern zu tun habe, die Spammen und sich im Forum mit sich selbst unterhalten will ich heerausfinden, welche Accounts gefakte sind und welche nicht.

Hierfür habe ich folgende Liste mit Werten (vereinfacht dargestellt):

Userid // IP Adresse
1 // IP Address 13
2 // IP Address 23
1 // IP Address 12
4 // IP Address 56
9 // IP Address 2
5 // IP Address 12
2 // IP Address 56

Wie man sieht nutzt zum Beispiel der User 2 die IP 56 und die 23.
Da der User 9 auch die 23 benutzt gehört er wahrscheinlich zur selben Person. Genauso wie User 4.
So haben wir für die erste gruppe von IDs und IPs folgende Menge:

Menge 1: Useris 2, IP Adresse 56, IP Adress 23, Userid 9, Userid 4

In der zweiten Gruppe ist User 1 mit der IP 13 und IP 12.
Die IP 12 wird aber auch von User 5 benutzt. Also ergibt sich folgende Menge:

Menge 2: Userid 1, Userid 5, IP Adresse 13, IP Adresse 12.

Ich soche nun eine Möglichkeit dies mit einem Code einer Schleife oder was auch immer hinzubekommen. Allerdings scheiter ich. Hat jemand eine Idee?

  1. Userid // IP Adresse
    1 // IP Address 13
    2 // IP Address 23
    1 // IP Address 12
    4 // IP Address 56
    9 // IP Address 2
    5 // IP Address 12
    2 // IP Address 56

    Wie man sieht nutzt zum Beispiel der User 2 die IP 56 und die 23.
    Da der User 9 auch die 23 benutzt gehört er wahrscheinlich zur selben Person. Genauso wie User 4.

    Ich soche nun eine Möglichkeit dies mit einem Code einer Schleife oder was auch immer hinzubekommen. Allerdings scheiter ich. Hat jemand eine Idee?

    Hast du die Beiträge in einer SQL-Datenbank? Dann wäre SQL dein Werkzeug, dort select mit group by.

    Andere Datenbankarten bieten ebenfalls spezialisierte Möglichkeiten, Daten zu gruppieren. PHP bräuchtest du, falls deine Tabelle wirklich nur in einer Textdatei stecken. Das wäre dann aber wohl die schlechtmöglichste Variante, daher meine Frage nach der Datenbankart.

    1. Ich habe sie in einer Datenbank, und speicher die werte danach zusätzlich in ein Array. Man kann also das Problem mit Mysql und php lösen. Aber ich glaube das eine einfache Groupby anfrage hier nicht das gewünschte ergebniss liefert. Habe auch schon

        
      SELECT user_id, GROUP_CONCAT(DISTINCT ip_address SEPARATOR ', ')  
      FROM TABLE_NAME GROUP BY user_id  
      
      

      probiert. Bringt auch nichts, wie gesagt es ist keine einfache Gruppierung.

  2. Aloha ;)

    Du suchst also sowas wie array_flip(), nur dass bei dir ALLE keys mit einem bestimmten Wert erhalten bleiben sollen. Ich versuch mich mal an einer selbstgebastelten Funktion...

    Oder doch nicht, denn wie ich gerade festgestellt habe, hast du uns noch nicht erklärt in welcher Form deine Daten vorliegen. Bevor ich jetzt hier also irgendwas Array-basiertes zusammenbastel wüsste ich gerne schon vorher, ob du überhaupt ein Array vorliegen hast (ich meine: nein).

    Klär uns also bitte zunächst besser über die Natur deiner "Liste" in ihrer PHP-Repräsentation auf. Mit den von dir gegebenen Informationen kann imho keiner hier wirklich arbeiten... Schon gar nicht auf PHP-Basis mit Codebeispiel...

    Grüße,

    RIDER

    --
    Camping_RIDER a.k.a. Riders Flame a.k.a. Janosch Zoller
    ch:? rl:| br:> n4:? ie:% mo:| va:) js:) de:> zu:) fl:( ss:| ls:[
    1. Aloha ;)

      Und ja, ich weiß, dass du geschrieben hast, dass es in ein Array eingelesen wird. Mich würde aber interessieren, wie das Array dann aussieht - denn ein simples eindimensionales Array mit userid als Schlüssel und IP-Addresse als Wert kann es nicht sein wegen doppelt vorkommender userid's. Das wäre nämlich das gewesen, was ich nach deiner Darstellung zunächst im Kopf hatte. Und ich will ungern noch dreimal anfangen mir Gedanken zu machen ;)

      Grüße,

      RIDER

      --
      Camping_RIDER a.k.a. Riders Flame a.k.a. Janosch Zoller
      ch:? rl:| br:> n4:? ie:% mo:| va:) js:) de:> zu:) fl:( ss:| ls:[
      1. Aloha, ich habe nun schon was gebastelt und es ist ein Monster geworden. Aber es veranschaulicht was ich vorhabe und ich wüsste gerne ob es einfacher geht. Sollte auch deine Frage klären.

        Folgende Funktion wird benötigt um zu prüfen ob ein Value im Multidimensionalen Array vorhanden ist:

          
        function in_array_r($needle, $haystack, $strict = false) {  
            foreach ($haystack as $key => $item) {  
                if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && in_array_r($needle, $item, $strict))) {  
                    return $key;  
                }  
            }  
            return false;  
        }  
        
        

        Folgendes Array Muster dient als Grundlage:

        $userids_using_same_ip[$ipadresss] = array("$userid1,$userid2 ....);

          
        /**  
        Das wird nachher mein Array indem ich die Gruppen hinter dem sich ein und die selbe person verbiergt gespeichert wird.. Gruppen nenne ich Clouds:  
        **/  
        $sameuserandidcloud = array();  
          
          
        foreach($userids_using_same_ip as $ip => $userids) {  
            foreach($userids_using_same_ip[$ip] as $userid) {  
          
                 // Hier habe ich die IP und die Userid  
        	$checkip = in_array_r($ip, $sameuserandidcloud);  
        	$checkuserid = in_array_r($userid, $sameuserandidcloud);  
        	if($checkip==false && $checkuserid==false) {  
        	     //Neue Cloud erstellen  
                     $cloundnr++;  
        	     if(!is_array($sameuserandidcloud[$cloundnr])) $sameuserandidcloud[$cloundnr] = array();  
        	     array_push($sameuserandidcloud[$cloundnr],$ip,$userid);	  
                }  
                else {  
                   if($checkip != false) array_push($sameuserandidcloud[$checkip],$ip,$userid);  
        	   elseif($checkuserid != false) array_push($sameuserandidcloud[$checkuserid],$ip,$userid);  
                }  
            }  
        }  
        
        

        Soweit so gut, ich habe hier nun schon das $sameuserandidcloud array vorbereitet und die werte sehen auch schon gut aus. Allerdings kann es passieren, da das array in der übergeordneten Schleife gebaut wird, dass IDs oder IPs obwohl sich später ein zusammenhang zeigen würde, in unterschiedliche clouds gespeichert werden. Daher muss ich das Array nochmal durchlaufen:

          
        while($loop!=1) {  
        	$break=0;  
        	$loop=1;  
        	foreach($sameuserandidcloud as $cloudid => $idanduseridarray) {  
        		$break=0;  
        		foreach($sameuserandidcloud[$cloudid] as $ipOrUserid) {  
        			$check = in_array_r($ipOrUserid, $sameuserandidcloud);  
        			if($check != false && $check != $cloudid) {  
        				array_push($sameuserandidcloud[$check],$sameuserandidcloud[$cloudid][0]);  
        				unset($sameuserandidcloud[$cloudid]);  
        				$break = 1;  
        				$loop = 0;  
        				break;  
        			}  
        		}  
        	        if($break==1) break;  
                }  
        	echo $break;  
        }  
        
        

        Ich laufe das Array praktisch durch und gucke ob eine Userid oder eine IP in einem anderem Cloudarray noch gespeichert ist, falls ja löse ich das bestehende auf und speicher die werte daraus in die andere cloud. danach beende ich die schleifen und lasse den code erneut durchlaufen, solange bis kein Wert mehr in einer anderen Cloud gefunden werden kann.

        Was meint ihr? Schöne Lösung oder habe ich ein Monster erschaffen?

        Mir ist klar, das dieser Code schnell bei vielen Datenmengen in die Knie gehen kann, gibt es schönere Lösungen?

        1. Aloha ;)

          Mir ist klar, das dieser Code schnell bei vielen Datenmengen in die Knie gehen kann, gibt es schönere Lösungen?

          Ich kann dir nur anbieten, wie ich das lösen würde:

          function flip_array_2dim ($array) {  
            
              $ret = Array();  
            
              foreach ($array as $userid => $subarr) {  
            
                  foreach ($subarr as $ip) {  
            
                      if (!isset($ret[$ip])) {  
            
                          $ret[$ip] = Array();  
            
                      }  
            
                      $ret[$ip][] = $userid;  
            
                  }  
            
              }  
            
              return $ret;  
            
          }
          

          Die Funktion bekommt dann ein zweidimensionales $array gefüttert, das etwa die folgende Struktur hat (Pseudocode):

          $array = Array(... userid1 => Array(ip1,ip2,...) ...)

          und gibt ein Array (in der Funktion $ret genannt) zurück in der Form

          $ret = Array(... ip1 => Array(userid1,userid2,...) ...)

          Bin gespannt, ob das dein Problem nicht etwas vereinfacht. Das war das, woran ich zunächst gedacht hatte. Ansonsten ist dein Weg denke ich schon gut, viel einfacher wird es kaum gehen. (Denn ein solches Matching ist immer aufwendig) Mir zumindest fällt sonst auch nicht viel ein.

          Grüße,

          RIDER

          --
          Camping_RIDER a.k.a. Riders Flame a.k.a. Janosch Zoller
          ch:? rl:| br:> n4:? ie:% mo:| va:) js:) de:> zu:) fl:( ss:| ls:[
  3. Hallo liebe Selfhtml-Community,

    Ich soche nun eine Möglichkeit dies mit einem Code einer Schleife oder was auch immer hinzubekommen. Allerdings scheiter ich. Hat jemand eine Idee?

    Was hättest Du denn gerne, pro User-ID ein Array mit IP-Adressen oder pro IP-Adresse ein Array mit User-IDs?

    Dann wäre noch die Frage, was Du damit machen willst ;)

    Frohes Fest.

  4. Hallo,

    Ich habe ein Forum wo jeder Beitrag mit einer Userid und einer IP Adresse gespeichert wird. Da ich mit gefakten Usern zu tun habe, die Spammen und sich im Forum mit sich selbst unterhalten will ich heerausfinden, welche Accounts gefakte sind und welche nicht.

    Ist dir bewusst, dass es tatsächlich unterschiedliche Personen sein könnten, die die selbe IP verwenden? Z.B. könnte sie in einem Intranet sitzen, das nach außen hin nur eine IP besitzt, intern aber viele User verwaltet.

    Gruß
    Kalk

    1. Hi,

      Ist dir bewusst, dass es tatsächlich unterschiedliche Personen sein könnten, die die selbe IP verwenden? Z.B. könnte sie in einem Intranet sitzen, das nach außen hin nur eine IP besitzt, intern aber viele User verwaltet.

      oder eine Familie oder WG, in der verschiedene Nutzer über denselben Router nach draußen gehen. Oder Gäste eines Hotels oder Restaurants, die dessen WLAN-Hotspot nutzen.

      Ciao,
       Martin

      --
      Warum können wir heute so sicher sagen, dass Gott keine Frau sein kann?
      Weil dann nach "Es werde Licht" der nächste Satz "Wie sieht denn das hier aus?!" gewesen wäre.
      Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(