Mein Name ist Nobody: PHP | Array - gibt es soetwas wie GROUP BY ?

Hi,

ich habe ein PHP Array gefüllt mit Zahlenwerten: $array = array("1", "6", "1", "8");

Ich suche eine PHP Funktion, die mir die häufigkeit der Werte zählen kann. Also Wert 1 ist 2 mal, 6 =1 usw. Ähnlich der MYSQL Funktion Group by Count.

Meine erste Idee wäre ein foreach, und ein weiteres Array bauen dann mit gegenchecks und zählern, falls vorhanden +1 ...

Das muss doch aber auch einfacher gehen oder?

Danke Nobody

akzeptierte Antworten

  1. Moin,

    Ich suche eine PHP Funktion, die mir die häufigkeit der Werte zählen kann. Also Wert 1 ist 2 mal, 6 =1 usw. Ähnlich der MYSQL Funktion Group by Count.

    Die Funktion array_count_values() klingt doch da ganz vielversprechend …

    Gruß
    Tobias

    1. Hallo Tobias,

      vielen Dank für deine Nachricht. Du hast den Nagel auf den Kopf getroffen, genau so eine Funktion habe ich gesucht.

      Daumen hoch.

  2. @@Mein Name ist Nobody

    Ich suche eine PHP Funktion, die mir die häufigkeit der Werte zählen kann.

    Wo genau suchst du?

    Ich hab einfach auf php.net nach „Array“ gesucht, lande auf Arrays und finde auf Anhieb in der Liste die Methode „Zählt die Werte eines Arrays“.

    🖖 Живіть довго і процвітайте

    --
    When the power of love overcomes the love of power the world will know peace.
    — Jimi Hendrix
    1. Danke für den Hinweis. Ich hatte es wohl übersehen.

      Нехай сила буде з тобою

  3. Hallo,

    ich habe ein PHP Array gefüllt mit Zahlenwerten:
    $array = array("1", "6", "1", "8");

    ergänzend zu den Lösungshinweisen, die du schon bekommen hast:
    Das sind keine Zahlenwerte, sondern Strings.

    Einen schönen Tag noch
     Martin

    --
    Kundin zur Verkäuferin im Modegeschäft: "Sagen Sie, haben Sie auch Sachen von der Marke SALE? Die sind immer so schön günstig!"
    1. ergänzend zu den Lösungshinweisen, die du schon bekommen hast: Das sind keine Zahlenwerte, sondern Strings.

      Und schon haben wir ein typisches PHP-Problem.

      Ich habe mal das Beispiel aus der Doc probiert.

      <?php
      $array = array(1, "hello", 1, "world", "hello");
      print_r(array_count_values($array));
      

      Ausgabe:

      Array
      (
          [1] => 2
          [hello] => 2
          [world] => 1
      )
      

      Man könnte jetzt etwas wie „toll“ denken. Aber:

      <?php
      $array = array(1, "hello", "1", "world", "hello", 1.9);
      print_r(array_count_values($array));
      
      Warning: array_count_values(): Can only count string and
      integer values, entry skipped in /home/fastix/tmp/2.php on line 3
      Array
      (
          [1] => 2
          [hello] => 2
          [world] => 1
      )
      
      

      was auch so NICHT stimmt, denn var_dump($array) sagt:

      array(6) {
        [0]=>
        int(1)
        [1]=>
        string(5) "hello"
        [2]=>
        string(1) "1"     ### INT 1 != STRING 1: falsch gezählt!
        [3]=>
        string(5) "world"
        [4]=>
        string(5) "hello"
        [5]=>
        float(1.9)        ### Nicht gezählt!
      }
      
      

      Die Doc erklärt auch, wie diverse Werte in Keys umgewandelt werden - und zeigt die Hölle

      1. Hallo,

        Und schon haben wir ein typisches PHP-Problem.

        Die Doc erklärt auch, wie diverse Werte in Keys umgewandelt werden - und zeigt die Hölle

        Aber das halte ich für nicht relevant. Man hat entweder ein Array mit gleichartigen Daten, dann hat man das Typumwandlungsproblem nicht, oder das Array ist ein Datenwust aus unterschiedlichsten Typen. Dann ist dessen Zählung aber auch irrelevant, oder?

        Das Konzept, bei dem man in dein konstruiertes Problem läuft, möchte ich nicht wirklich sehen…

        Gruß
        Kalk

        1. Hallo,

          Und schon haben wir ein typisches PHP-Problem.

          Die Doc erklärt auch, wie diverse Werte in Keys umgewandelt werden - und zeigt die Hölle

          Aber das halte ich für nicht relevant.

          Hehe!

          Bei einem Array mit den Werten [ 0.4, 1.2, 0.4, 0.8] funktioniert array_count_values() auch nicht.

          Du meinst ernsthaft, DAS sei „nicht relevant“?

          1. Hallo,

            Bei einem Array mit den Werten [ 0.4, 1.2, 0.4, 0.8] funktioniert array_count_values() auch nicht.

            Du meinst ernsthaft, DAS sei „nicht relevant“?

            Im Prinzip ja. Für welche(n) Analyse, Anwendung oder usecase braucht man die jeweilige Anzahl der floatwerte?

            Gruß
            Kalk

            1. Hallo,

              Bei einem Array mit den Werten [ 0.4, 1.2, 0.4, 0.8] funktioniert array_count_values() auch nicht.

              Du meinst ernsthaft, DAS sei „nicht relevant“?

              Im Prinzip ja. Für welche(n) Analyse, Anwendung oder usecase braucht man die jeweilige Anzahl der floatwerte?

              usecase: Kindergeburtstag beim Raketenwilli:

              Es stehen 4 Teller mit je 1/8, 1/8, 1/4, 1/2-Stücken von ganzen Torten auf dem Tisch.

              Klein Raketenwilli wird gerade 9, ist verfressen wie ein Regiment Russen, darf die 1/4-Torten-Stücke und die 1/2-Torten-Stücke sofort futtern, wenn er ohne selbst zu zählen herausbekommt, wie viele Stücke dieser Größen auf den Tellern liegen. Mutti hat es schwierig gemacht und die Stücke jeweils verwürfelt. Klein Raketenwilli ist außerdem faul und will gar nicht selbst zählen!

              Mit meiner (inzwischen erweiterten) Klasse klappt das:

              <?php
              
              class strong_array_values_counter {
              	protected $keys=[];
              	protected $counts=[];
              	
              	function __construct( $arr ) {
              		foreach ( $arr as $v ) {
              			if ( !  in_array( $v, $this->keys, true ) )  {
              				$pos = count( $this->keys ) ;
              				$this->keys[$pos] = $v;
              				$this->counts[$pos] = 1;
              			} else {
              				$pos = $this->findPos( $v );
              				$this->counts[$pos]++;
              			}
              		}
              	}
              	private function findPos( $v ) {
              		for ( $i=0; $i < count( $this->keys ); $i++ ) {
              			if ( $this->keys[$i] === $v ) {
              				return $i;
              			}
              		} 
              		return false;
              	}
              	
              	public function get_Keys_Values() {
              		$ret=[];
              		for ( $i=0; $i < count( $this->keys); $i++ ) {
              			$ret[] = [ $this->keys[ $i ], $this->counts[ $i ] ];
              		}
              		return $ret;
              	} 
              	
              	public function get_Counts_By_Value( $v ) {
              		$pos = $this->findPos( $v );
              		return $this->counts[ $pos ];
              	} 	
              	
              	public function get_Counts_BetWeen( $v1, $v2, $includet=true, $intToFloat=false ) {
              		
              		if ( $intToFloat and gettype( $v1 ) == 'integer') settype($v1, 'double' );
              		if ( $intToFloat and gettype( $v2 ) == 'integer') settype($v2, 'double' );
              		
              		$typeOfV1 = gettype( $v1 );
              		$typeOfV2 = gettype( $v2 );
              		
              		
              		
              		if ( $typeOfV1 != $typeOfV2 ) {
              			trigger_error('Die übergebenen Werte sind nicht typgleich. Es findet kein Vergleich statt.', E_USER_WARNING );
              			return false;
              		}
              		
              		if ( $v1 > $v2 ) {
              			$t = $v1; $v1 = $v2; $v2 = $t;
              		}
              		
              		$founds = 0;
              		
              		for ( $i=0; $i < count( $this->keys ); $i++ ) {
              			$t = $this->keys[ $i ];
              			if ( $intToFloat and gettype( $t ) == 'integer') settype( $t, 'double' );
              			if ( $includet ) {
              				if (
              						gettype( $t ) == $typeOfV1
              					and $t >= $v1
              					and $t <= $v2
              				)  {
              					$founds += $this->counts[ $i ];
              				}
              			} else {
              				if (
              						gettype( $t ) == $typeOfV1
              					and $t > $v1
              					and $t < $v2
              				)  {
              					$founds += $this->counts[ $i ];
              				}				
              			}
              		}
              		return $founds;
              	}
              }
              
              <?php
              ### Herstellen
              $ar = [];
              $teller = [ (1/8), (1/8), (1/4), (1/2) ];
              ### Servieren
              for ( $i = 0; $i < 4; $i++ ) {
              	shuffle( $teller );
              	foreach ( $teller as $stück ) {
              		array_push( $ar, $stück ) ;
              	}
              }
              
              ### Muttis Kontrolle:
              print_r( $ar );
              
              ### Nicht SELBST zählen:
              require_once 'strong_array_values_counter.php';
              $o = new strong_array_values_counter( $ar );
              echo $o->get_Counts_BetWeen( (1/4), (1/2), true, true ) . PHP_EOL;
              

              Anmerkung: Für den Raketenwilli und seine Cousine wurden einst tatsächlich je 2 Torten gemacht. Vergebliche Mühsal diese zu schneiden ...

              Anmerkung: Das ist natürlich nicht der einzige usecase. Nimm Messreihen, Ausschussquoten, ...

              Anmerkung: Meine Klasse kann neben Strings, Floats und Integers sogar Objekte, Arrays und anderes Zeug gruppiert zählen, welches sich als Elemente eines Arrays im Speicher tummeln.

              1. Hallo,

                Ok, bei Torten (und Weckern) muss ich mich geschlagen geben…

                Gruß
                Kalk

                1. @@Tabellenkalk

                  Ok, bei Torten (und Weckern) muss ich mich geschlagen geben…

                  WAS? DU KRIEGST 28 DURCH 7 NICHT RAUS?

                  🖖 Живіть довго і процвітайте

                  --
                  When the power of love overcomes the love of power the world will know peace.
                  — Jimi Hendrix
                  1. Hallo,

                    WAS? DU KRIEGST 28 DURCH 7 NICHT RAUS?

                    Kurzfassung: stell dir vor du hast 28 Torten und musst um 7 Uhr raus…

                    Gruß
                    Kalk

              2. @@Raketenwilli

                Das ist natürlich nicht der einzige usecase. Nimm Messreihen

                Halte ich für keinen Usecase. Wenn da zwei Messwerte „gleich“ sind, sind sie das im Rahmen der Messgenauigkeit. Aber sie sind nicht wirklich gleich.

                Heißt, ich sehe den Usecase nicht, array_count_values() auf ein Array von Floats anwenden zu wollen.

                🖖 Живіть довго і процвітайте

                --
                When the power of love overcomes the love of power the world will know peace.
                — Jimi Hendrix
                1. Hallo,

                  Das ist natürlich nicht der einzige usecase. Nimm Messreihen

                  Halte ich für keinen Usecase. Wenn da zwei Messwerte „gleich“ sind, sind sie das im Rahmen der Messgenauigkeit. Aber sie sind nicht wirklich gleich.

                  sp isses, und selbst wenn sie im Rahmen der Darstellungsgenauigkeit, z.B. der Darstellung im IEEE-Fließkommaformat, gleich sind (was theoretisch möglich wäre), ist das in der Regel irrelevant.

                  Bei Messwerten ist normalerweise nur relevant, dass sie innerhalb einer vorgegebenen Spanne oder diesseits/jenseits einer bestimmten Schwelle liegen.

                  Heißt, ich sehe den Usecase nicht, array_count_values() auf ein Array von Floats anwenden zu wollen.

                  +1

                  Einen schönen Tag noch
                   Martin

                  --
                  Kundin zur Verkäuferin im Modegeschäft: "Sagen Sie, haben Sie auch Sachen von der Marke SALE? Die sind immer so schön günstig!"
                2. Hi,

                  Halte ich für keinen Usecase. Wenn da zwei Messwerte „gleich“ sind, sind sie das im Rahmen der Messgenauigkeit. Aber sie sind nicht wirklich gleich.

                  Eben. Floats/Doubles niemals auf Gleichheit prüfen, immer nur auf eine Differenz kleiner Epsilon (wobei Epsilon größer sein muß als die kleinste darstellbare Differenz)

                  cu,
                  Andreas a/k/a MudGuard

      2. Wie, wann und warum array_count_values() untauglich ist und sogar falsche Ergebnisse liefert habe ich gezeigt.

        Als „Raketenwilli“ will ich natürlich so ein Problem gelöst sehen… Hier mein erster Ansatz:

        <?php
        $array = array("1", "hello", 1, "world", "hello");
        echo "Das Array:\n";
        var_dump( $array );
        
        $strong_counter =  New strong_array_values_counter( $array );
        echo "\nDas Objekt:\n";
        var_dump( $strong_counter);
        
        echo "Werte und Vorkommen in zwei Arrays:\n";
        var_dump( $strong_counter->get_Keys_Values() );
        
        echo "\nVorkommen von 1 und \"1\":\n";
        echo 'STR  "1":' . $strong_counter->get_Counts_By_Value( "1" ) . PHP_EOL;
        echo 'INT   1 :' . $strong_counter->get_Counts_By_Value( 1 ) . PHP_EOL;
        
        
        
        class strong_array_values_counter {
        	protected $keys=[];
        	protected $counts=[];
        	
        	function __construct( $arr ) {
        		foreach ( $arr as $v ) {
        			if ( !  in_array( $v, $this->keys, true ) )  {
        				$pos = count( $this->keys ) ;
        				$this->keys[$pos] = $v;
        				$this->counts[$pos] = 1;
        			} else {
        				$pos = $this->findPos( $v );
        				$this->counts[$pos]++;
        			}
        		}
        	}
        	private function findPos( $v ) {
        		for ( $i=0; $i < count( $this->keys ); $i++ ) {
        			if ( $this->keys[$i] === $v ) {
        				return $i;
        			}
        		} 
        		return false;
        	}
        	
        	public function get_Keys_Values() {
        		$ret=[];
        		for ( $i=0; $i < count( $this->keys); $i++ ) {
        			$ret[] = [ $this->keys[ $i ], $this->counts[ $i ] ];
        		}
        		return $ret;
        	} 
        	
        	public function get_Counts_By_Value( $v ) {
        		$pos = $this->findPos( $v );
        		return $this->counts[ $pos ];
        	} 	
        	
        }
        

        Putput:

        Das Array:
        array(5) {
          [0]=>
          string(1) "1"
          [1]=>
          string(5) "hello"
          [2]=>
          int(1)
          [3]=>
          string(5) "world"
          [4]=>
          string(5) "hello"
        }
        
        Das Objekt:
        object(strong_array_values_counter)#1 (3) {
          ["keys":protected]=>
          array(4) {
            [0]=>
            string(1) "1"
            [1]=>
            string(5) "hello"
            [2]=>
            int(1)
            [3]=>
            string(5) "world"
          }
          ["types":protected]=>
          array(0) {
          }
          ["counts":protected]=>
          array(4) {
            [0]=>
            int(1)
            [1]=>
            int(2)
            [2]=>
            int(1)
            [3]=>
            int(1)
          }
        }
        Werte und Vorkommen in zwei Arrays:
        array(4) {
          [0]=>
          array(2) {
            [0]=>
            string(1) "1"
            [1]=>
            int(1)
          }
          [1]=>
          array(2) {
            [0]=>
            string(5) "hello"
            [1]=>
            int(2)
          }
          [2]=>
          array(2) {
            [0]=>
            int(1)
            [1]=>
            int(1)
          }
          [3]=>
          array(2) {
            [0]=>
            string(5) "world"
            [1]=>
            int(1)
          }
        }
        
        Vorkommen von 1 und "1":
        STR  "1":1
        INT   1 :1