Zur Navigation

Alternative zu array_intersect

1 AndiN

Hallo Jörg,
ich versuche mich gerade an der Funktion array_intersect.


$array_ergebnisIDs = array_intersect($array_ausstattung1,$array_ausstattung2,$array_ausstattung3,$array_ausstattung4,$array_ausstattung5,$array_ausstattung6,$array_ausstattung7);

Die Funktion soll mir in ein Array mit allen Werte liefern die in allen Ausstattung-Arrays vorkommen. Mein Problem ist nun allerdings, dass eines oder mehrere Arrays auch leer sein können. In diesem Fall für array_intersect zu einem leeren Ergebnis. SInnvoller wäre es, wenn die leeren Arays beim Vergleich quasi ignoriert werden. Gibt es da noch eine intelligentere Möglichkeit ohne, dass ich vorher alle Arrays auf Inhalt checken und dann jenachdem welches Array Werte beinhaltet jedes mit jedem vergleichen muss?

Gruß Andreas

19.06.2012 15:42

3 AndiN

Ich habe das Code-Beispiel bei mir eingefügt.
Nun sieht es so aus, also würde array_intersect alle IDs ausgeben die mindestens in zwei der Arrays die ich vergleiche enthalten sind.

Array1           Array2          Array3
[0] => 14        [0] => 21       [0] => 9
[1] => 20        [1] => 22       [1] => 14
[2] => 21        [2] => 27       [2] => 20
[3] => 27        [3] => 29       [3] => 21
[4] => 40        [4] => 30       [4] => 27
[5] => 55        [5] => 31       [5] => 55
[6] => 56        [6] => 40       [6] => 56
[7] => 57        [7] => 55       [7] => 57
[8] => 58        [8] => 56       [8] => 58
[9] => 61        [9] => 57       [9] => 59
                 [10] => 58      [10] => 61
                 [11] => 59           
                 [12] => 60           
                 [13] => 61

Das Ergebnis-Array (Array4) nach array_intersect sieht so aus:

Array4(
[0] => 14	
[1] => 20	
[2] => 21	
[3] => 27	
[5] => 55	
[6] => 56	
[7] => 57	
[8] => 58	
[9] => 61)

Was ich will wäre allerdings eine Ausgabe von Werten die wirklich in allen beteiligten Arrays vorhanden sind:

Array5(
[0] => 21	
[1] => 27	
[2] => 55	
[3] => 56	
[4] => 57	
[5] => 58	
[6] => 61)

Auffällig ist, dass im Array4 - welches eigentlich die Schnittmenge sein soll - der Array-Eintrag an Position 4 fehlt.

Mein Code sieht so aus:

$kb = array('array_ausstattung1','array_ausstattung2','array_ausstattung3','array_ausstattung4','array_ausstattung5');
$out = $array_ausstattung1;
foreach($kb as $k)
{
	if(!empty(${$k}))
		$array_suchergebnisIDs = array_intersect($out,${$k});
}

20.06.2012 11:30

4 Rudy

so klappts bei mir:

<?php

error_reporting(E_ALL);

$array_ausstattung1 = array(14,20,21,27,40,55,56,57,58,61);
$array_ausstattung2 = array(21,22,27,29,30,21,40,55,56,57,58,59,60,61);
$array_ausstattung3 = array(9,14,20,21,27,55,56,57,58,59,61);

for ($i=0,$result=array(); $i<6; $i++) {
  $arr =& ${'array_ausstattung'.$i};
  if (isset($arr)) {
     $result = empty($result) ? $arr : array_intersect($result, $arr);
  }
}

print_r($result);

20.06.2012 14:41

5 AndiN

Bei mir mus es noch etwas anders funktionieren:

for ($i=1,$result=array(); $i<8; $i++)
			{
				$arr =& ${'array_ausstattung'.$i};
				if (isset($arr))
					$result = empty($result) ? $arr : array_intersect($result, $arr);
			}
			$array_suchergebnisIDs = array_intersect($result,$array_alles);

Ich muss am Ende das Array welches die Werte anzeigt die bei allen Ausstattungs-Arrays vorhanden sind nochmal mit einem Gesamt-Array ($array_alles) vergleichen.


Ich bekomme nun folgende Fälle:

1) alle Ausstattungsarrays leer => funktioniert

2) ein Ausstattungsarray gefüllt => IDs die in $result und in $array_alles vorkommen sind in $array_suchergebnisIDs doppelt drin. Zusätzlich sind noch die IDs von $result und von $array_alles drin.

3) zwei Ausstattungsarrays gefüllt => IDs die in $result und in $array_alles vorkommen sind in $array_suchergebnisIDs dreifach drin. Zusätzlich sind noch die IDs von $result und von $array_alles drin.

4) drei Ausstattungsarrays gefüllt => IDs die in $result und in $array_alles vorkommen sind in $array_suchergebnisIDs vierfach drin. Zusätzlich sind noch die IDs von $result und von $array_alles drin.

usw.

Es sieht also so aus als würde mein zusätzliches array_intersect die beiden Arrays zusammenkopieren anstatt nach doppelten Werten filtern.

Nachtrag:
Hab gerade rausgefunden. dass in der $result die IDs so oft drinstehen wie sie in den Ausstattungsarrays auch vorkommen. Wenn sie in 2 Ausstattungsarrays vorkommen stehen diese IDs doppelt drin. Bei mehrfachem Vorkommen entsprechend mehrfach.

20.06.2012 15:34 | geändert: 20.06.2012 15:43

6 Rudy

Wenn Du alle Werte aus $array_alles willst, die in auch in $result enthalten sind, drehe die Parameter um:

$array_suchergebnisIDs = array_intersect($array_alles, $result);

Löst es das? Was mir noch auffällt: Wenn die Arrays auch leer sein können und trotzdem definiert sind, nimm statt

if (isset($arr))

zusätzlich

if (isset($arr) && !empty($arr)) 

Falls noch Fehler auftreten poste bitte ein Beispielskript so wie anfangs, dann kann ich Dir leichter helfen.

20.06.2012 15:40

7 Jörg Kruse

Nochmal zu dem Code weiter oben in Beitrag 3:

$kb = array('array_ausstattung1','array_ausstattung2','array_ausstattung3','array_ausstattung4','array_ausstattung5');
$out = $array_ausstattung1;
foreach($kb as $k)
{
	if(!empty(${$k}))
		$array_suchergebnisIDs = array_intersect($out,${$k});
}

$out und $array_suchergebnisIDs dürfen hier nicht unterschiedlich benannt werden. So fängst du nach jedem Schleifendurchlauf wieder mit $array_ausstattung1 an, statt mit der mittlerweile ermittelten Schnittmenge

20.06.2012 15:41 | geändert: 20.06.2012 15:42

8 Rudy

Nachtrag:
Hab gerade rausgefunden. dass in der $result die IDs so oft drinstehen wie sie in den Ausstattungsarrays auch vorkommen. Wenn sie in 2 Ausstattungsarrays vorkommen stehen diese IDs doppelt drin. Bei mehrfachem Vorkommen entsprechend mehrfach.

Dazu steht was auf PHP.net, letzter User-Kommentar. Offenbar funktioniert array_intersect mit doppelten Werten nicht zuverlässig. Eine alternative Funktion ist vorhanden.

http://it2.php.net/manual/de/function.array-intersect.php#104063

20.06.2012 15:48

9 AndiN

$kb = array('array_alles','array_ausstattung1','array_ausstattung2','array_ausstattung3','array_ausstattung4','array_ausstattung5');

$array_suchergebnisIDs = $array_alles;
foreach($kb as $k)
{
	if(!empty(${$k}))
		$array_suchergebnisIDs = array_intersect($array_suchergebnisIDs,${$k});
}

Wenn ich das jetzt so nach Jörgs Angabe so ändere bekomme ich zwar keine mehrfachen Werte, jedoch ist das Ergebnis auch noch falsch:

IDs mit Attribut1: 14, 20, 21, 40
IDs mit Attribut2: 20, 21, 27
IDs mit Attribut1 und Attribut2: 14, 20, 21, 27, 40

Richtig müsste es sein: 20, 21

20.06.2012 15:55 | geändert: 20.06.2012 15:55

10 Rudy

Beide Varianten liefern bei mir dieses Ergebnis bei nur 2 Ausgangsarrays, kannst Du ggf. die Definitionen aller Arrays inkl. array_alles und das gewünschte Ergebnis posten?

<?php

error_reporting(E_ALL);
$array_alles = array(14, 20, 21, 40);
$array_ausstattung1 = array(20, 21, 27);
$array_ausstattung2 = array(); //21,22,27,29,30,21,40,55,56,57,58,59,60,61);
$array_ausstattung3 = array(); //9,14,20,21,27,55,56,57,58,59,61);

for ($i=0,$array_suchergebnisIDs=$array_alles; $i<8; $i++) {
  $arr =& ${'array_ausstattung'.$i};
  if (isset($arr) && !empty($arr)) {
     $array_suchergebnisIDs = array_intersect($array_suchergebnisIDs, $arr);
  }
}

print_r($array_suchergebnisIDs);


$kb = array('array_alles', 'array_ausstattung1','array_ausstattung2','array_ausstattung3','array_ausstattung4','array_ausstattung5');
$array_suchergebnisIDs = $array_alles;
foreach($kb as $k) {
	if(!empty(${$k}))
		$array_suchergebnisIDs = array_intersect($array_suchergebnisIDs,${$k});
}

print_r($array_suchergebnisIDs);

Ergebnis:

Array ( [1] => 20 [2] => 21 ) Array ( [1] => 20 [2] => 21 ) 

Nachtrag, kürzer:

for ($i=1,$array_suchergebnisIDs=$array_alles; $i<8 && ($arr =& ${'array_ausstattung'.$i}); $i++) {
  if (isset($arr) && !empty($arr)) {
     $array_suchergebnisIDs = array_intersect($array_suchergebnisIDs, $arr);
  }
}

20.06.2012 16:09 | geändert: 20.06.2012 16:20