array_intersect con un numero variabile di array

phpillole feb 06, 2019

array_intersect() è una delle tante pratiche funzioni di php per manipolare gli array e come suggerisce il nome viene utilizzato per trovare, tra tutti gli array passati come argomento, gli elementi comuni a quello fornito.
Per trovare l'intersezione tra degli insiemi, in pratica.

array_intersect ( array $array1 , array $array2 [, array $... ] ) : array

Recentemente mi sono trovato di fronte alla necessità di utilizzare questo metodo su un numero variabile di array - o meglio, avevo un array associativo dal numero variabile di elementi chiave => valore dal quale dovevo estrapolare l'elemento comune a tutti gli array presi in considerazione.
Questo il JSON di partenza:

{"serie_1":["1920","1919","1802","1800","1798","1796","1794","1792"], "serie_4":["1919","1796"], "serie_3":["1920","1919"], "serie_5":["1920","1919","1852","1850","1848","1846","1844","1842","1840","1838","1836","1818","1816","1814","1812","1810","1808","1806","1804","1802","1800","1798","1796","1794","1792"]}

I problemi qui sono due: il numero di serie disponibili non è sempre fisso (da 1 a 5), e alcune di queste serie possono esssere presenti  ma vuoti (ossia senza alcun elemento). Dopo alcuni tentativi e ricerche su StackOverflow sono arrivato a questa soluzione:


// Riduco l'array di partenza rimuovendo tutti gli array vuoti
$filtrati = array_filter($sequenza, function($val) {
	return !empty($val);
});

$comune = call_user_func_array('array_intersect', $filtrati);

Bisogna però fare attenzione : `array_intersect()` si aspetta almeno due elementi (un array di base ed uno per confrontarne gli elementi), quindi bisogna controllare che l'array di  input contenga almeno due elementi. Sistemato un po' diventa:


$serie = json_decode('{"serie_1":["1920","1919","1802","1800","1798","1796","1794","1792"], "serie_4":["1919","1796"], "serie_3":["1920","1919"], "serie_5":["1920","1919","1852","1850","1848","1846","1844","1842","1840","1838","1836","1818","1816","1814","1812","1810","1808","1806","1804","1802","1800","1798","1796","1794","1792"]}', true);
 
/**
 * @param array $needle
 * @return mixed 
 */
function pickCommonElement($needle) {
	// Remove empty arrays
	$filtered = array_filter($needle, function($val) {
		return !empty($val);
	});
 
	if (count($filtered) > 1) {
	  $common = call_user_func_array('array_intersect', $filtered);  
	  $len = count($common);
 
	  if ($len == 1) {
		 return array_shift($common);
	  }
	}
	return null;
}

var_dump(pickCommonElement($serie));
string(4) "1919"

Qui uso array_shift($common); perchè array_intersect() mantiene le chiavi originali dell'array, e dovendo recuperare solo il primo elemento mi pareva il metodo più comodo e rapido per farlo.

Matteo Vignoli

Sviluppatore Web Full-Stack, autodidatta, curioso per natura, attualmente impiegato a Milano in ContactLab