Raketenwilli: Kindergeburtstag beim Raketenwilli

Beitrag lesen

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.