PHP Conference Japan 2024

array_intersect

(PHP 4 >= 4.0.1, PHP 5, PHP 7, PHP 8)

array_intersect計算陣列的交集

說明

array_intersect(陣列 $array, 陣列 ...$arrays): 陣列

array_intersect() 傳回一個陣列,其中包含 array 中所有在所有引數中都存在的值。請注意,鍵值會被保留。

參數

array

要檢查的主要值陣列。

arrays

用於比較值的陣列。

回傳值

回傳一個陣列,其中包含所有在 array 中的值,且這些值也存在於所有其他參數中。

更新日誌

版本 說明
8.0.0 現在可以用只有一個參數來呼叫此函式。以前,至少需要兩個參數。

範例

範例 #1 array_intersect() 範例

<?php
$array1
= array("a" => "green", "red", "blue");
$array2 = array("b" => "green", "yellow", "red");
$result = array_intersect($array1, $array2);
print_r($result);
?>

上述範例會輸出:

Array
(
    [a] => green
    [0] => red
)

注意事項

注意 兩個元素被認為相等,若且唯若 (string) $elem1 === (string) $elem2。 換句話說:當它們的字串表示法相同時。

參見

新增註釋

使用者貢獻的註釋 33 則註釋

stuart at horuskol dot co dot uk
16 年前
一個更清楚地說明此函式如何保留鍵值的範例

<?php

$array1
= array(2, 4, 6, 8, 10, 12);
$array2 = array(1, 2, 3, 4, 5, 6);

var_dump(array_intersect($array1, $array2));
var_dump(array_intersect($array2, $array1));

?>

會產生以下結果

array(3) {
[0]=> int(2)
[1]=> int(4)
[2]=> int(6)
}

array(3) {
[1]=> int(2)
[3]=> int(4)
[5]=> int(6)
}

如果腳本稍後會用到這些鍵值,那麼記住傳遞陣列給函式的順序就很重要。
theking at king dot ma
2 年前
我使用 array_intersect 來快速檢查 $_GET 參數;

<?php declare(strict_types=1)

$_params = ['cust_id','prod_id'];
$_params_check = array_intersect(array_keys($_GET),$_params);
if(
count($_params_check) !== count($_params)) {
header("HTTP/1.1 400 Bad Request");
die();
}
?>

如果 $_GET 中缺少 cust_id 或 prod_id 或兩者都缺少,檔案將會以 400 錯誤終止。但顯然它也可以用於 $_POST 和 $_REQUEST。
匿名
3 年前
array_intersect 使用值,不使用回呼函式
array_uintersect 使用值,回呼函式接收值
array_intersect_key 使用鍵,不使用回呼函式
array_intersect_ukey 使用鍵,回呼函式接收鍵
array_intersect_assoc 使用鍵和值,不使用回呼函式
array_intersect_uassoc 使用鍵和值,回呼函式僅接收鍵
array_uintersect_assoc 使用鍵和值,回呼函式僅接收值
array_uintersect_uassoc 使用鍵和值,一個回呼函式接收鍵,另一個接收值。
Niels
18 年前
這裡有一個 array_union($a, $b)

<?php
// $a = 1 2 3 4
$union = // $b = 2 4 5 6
array_merge(
array_intersect($a, $b), // 2 4
array_diff($a, $b), // 1 3
array_diff($b, $a) // 5 6
); // $u = 1 2 3 4 5 6
?>
sapenov at gmail dot com
19 年前
如果您需要提供任意數量的參數
給 array_intersect() 或其他陣列函式,
請使用以下函式

$full=call_user_func_array('array_intersect', $any_number_of_arrays_here);
Shawn Pyle
15 年前
array_intersect 處理陣列中重複項目的方式不同。如果第一個陣列中有重複項,則所有匹配的重複項都將被返回。如果後續任何陣列中有重複項,則不會返回它們。

<?php
array_intersect
(array(1,2,2),array(1,2,3)); //=> array(1,2,2)
array_intersect(array(1,2,3),array(1,2,2)); //=> array(1,2)
?>
yuval at visualdomains dot com
9 年前
使用 isset 來達到這個目的,速度快很多倍

<?php

$m
= range(1,1000000);
$s = [2,4,6,8,10];

// 使用 array_intersect 回傳所有同時存在於 $m 和 $s 的 $m 值
$tstart = microtime(true);
print_r (array_intersect($m,$s));
$tend = microtime(true);
$time = $tend - $tstart;
echo
"耗時 $time";

// 使用 array_flip 和 isset 回傳所有同時存在於 $m 和 $s 的 $m 值
$tstart = microtime(true);
$f = array_flip($s);
/* $f 現在看起來像這樣:
(
[2] => 0
[4] => 1
[6] => 2
[8] => 3
[10] => 4
)
*/
// $u 將存放交集的值
$u = [];
foreach (
$m as $v) {
if (isset(
$f[$v])) $u[] = $v;
}
print_r ($u);
$tend = microtime(true);
$time = $tend - $tstart;
echo
"耗時 $time";
?>

結果

陣列
(
[1] => 2
[3] => 4
[5] => 6
[7] => 8
[9] => 10
)
耗時 4.7170009613037
(
[0] => 2
[1] => 4
[2] => 6
[3] => 8
[4] => 10
)
耗時 0.056024074554443

array_intersect: 4.717
array_flip+isset: 0.056
blu at dotgeek dot org
20 年前
請注意,array_intersect 和 array_unique 無法有效處理多維陣列。
例如,如果您有

<?php

$orders_today
[0] = array('John Doe', 'PHP Book');
$orders_today[1] = array('Jack Smith', 'Coke');

$orders_yesterday[0] = array('Miranda Jones', 'Digital Watch');
$orders_yesterday[1] = array('John Doe', 'PHP Book');
$orders_yesterday[2] = array('Z? da Silva', 'BMW Car');

?>

如果您想知道今天和昨天是否有人購買了相同的商品,並且使用 array_intersect($orders_today, $orders_yesterday),您會得到以下結果:

<?php

Array
(
[
0] => Array
(
[
0] => John Doe
[1] => PHP Book
)

[
1] => Array
(
[
0] => Jack Smith
[1] => Coke
)

)

?>

但我們可以透過序列化內部陣列來解決這個問題
<?php

$orders_today
[0] = serialize(array('John Doe', 'PHP Book'));
$orders_today[1] = serialize(array('Jack Smith', 'Coke'));

$orders_yesterday[0] = serialize(array('Miranda Jones', 'Digital Watch'));
$orders_yesterday[1] = serialize(array('John Doe', 'PHP Book'));
$orders_yesterday[2] = serialize(array('Z? da Silva', 'Uncle Tungsten'));

?>

這樣 array_map("unserialize", array_intersect($orders_today, $orders_yesterday)) 將會返回

<?php

Array
(
[
0] => Array
(
[
0] => John Doe
[1] => PHP Book
)

)

?>

顯示今天和昨天購買相同商品的人 =)

[]s
dml at nm dot ru
13 年前
當輸入陣列具有重複值時,內建函數會返回錯誤的結果。
以下是可以正確運作的程式碼

<?php
function array_intersect_fixed($array1, $array2) {
$result = array();
foreach (
$array1 as $val) {
if ((
$key = array_search($val, $array2, TRUE))!==false) {
$result[] = $val;
unset(
$array2[$key]);
}
}
return
$result;
}
?>
matang dot dave at gmail dot com
9 年前
使用 array_intersect 函式時要注意值的類型,因為它不像 in_array 函式那樣有嚴格類型檢查的選項。

$array1 = array(true,2);
$array2 = array(1, 2, 3, 4, 5, 6);

var_dump(array_intersect($array1, $array2));

結果是
array(2) {
[0] => bool(true)
[1] => int(2)
}
Esfandiar -- e.bandari at gmail dot com
16 年前
關於陣列聯集:這裡有一個更快的版本 array_union($a, $b)

但這並非必要!請見下方。

<?php
// $a = 1 2 3 4
$union = // $b = 2 4 5 6
array_merge(
$a,
array_diff($b, $a) // 5 6
); // $u = 1 2 3 4 5 6
?>

使用 $a + $b 你會得到相同的結果。

注意:對於關聯式陣列,$a+$b 和 $b+$a 的結果是不同的,我認為這使用了 array_diff_key。

致敬, E
Malte
16 年前
延續 Terry 在 2006年2月7日 04:42 的貼文

如果你想將此函式用於有時具有相同值的陣列,它不會檢查它們在第二個陣列中出現的次數是否與第一個陣列相同。
所以我會在第二個陣列中找到該值時將其刪除

<?php
$firstarray
= array(1, 1, 2, 3, 4, 1);
$secondarray = array(4, 1, 6, 5, 4, 1);

//array_intersect($firstarray, $secondarray): 1, 1, 1, 4

foreach ($firstarray as $key=>$value){
if (!
in_array($value,$secondarray)){
unset(
$firstarray[$key]);
}else{
unset(
$secondarray[array_search($value,$secondarray)]);
}
}

//$firstarray: 1, 1, 4

?>
nthitz at gmail dot com
18 年前
如果已知陣列的大概大小,那麼這樣做似乎會快很多:<?php array_intersect($smallerArray, $largerArray); ?>,其中 $smallerArray 是項目較少的陣列。我只用長字串測試過,但我認為這在某種程度上是通用的。
theking2(at)king(dot)ma
11 個月前
更通用的參數檢查

<?php
/**
* 檢查請求中是否存在所有必要的參數
*
* @param mixed $request 任何 $_GET、$_POST、$_REQUEST
* @param mixed $required 必要的參數陣列
* @return bool 如果所有必要的參數都存在,則返回 true
*/
function check_params( array $request, array $required ): bool
{
$check = array_intersect( array_keys( $request ), $required );
return
count( $check ) === count( $required );
}
?>

像這樣使用
<?php
if( !check_params( $_GET, ['cust_id','prod_id'] ) {
header( "HTTP/1.1 400 Bad Request" );
echo
"Bad Request";
exit();
}
?>

讓我知道 PHP 中是否已經內建了類似的功能...
t dot wiltzius at insightbb dot com
20 年前
我需要將一個具有關聯鍵的陣列與另一個包含部分關聯陣列鍵的陣列進行比較。基本上,我只想返回原始陣列中的少數幾個項目,而我想返回的項目的鍵儲存在另一個陣列中。這很簡單(雖然解釋起來很複雜),但我找不到一個好的函式來比較值和鍵。所以我寫了這個相對簡單的函式

<?php

function key_values_intersect($values,$keys) {
foreach(
$keys AS $key) {
$key_val_int[$key] = $values[$key];
}
return
$key_val_int;
}

$big = array("first"=>2,"second"=>7,"third"=>3,"fourth"=>5);
$subset = array("first","third");

print_r(key_values_intersect($big,$subset));

?>

這將會返回

Array ( [first] => 2 [third] => 3 )
Yohann
14 年前
我使用 array_intersect 來任意排序一個陣列

<?php
$a
= array('one', 'two', 'three', 'four', 'five', 'six', 'seven', 'height', 'nine', 'ten');
$b = array('four', 'one', 'height', 'five')
var_dump(array_intersect($a, $b);
?>

會輸出

0 => 'one'
1 => 'four'
2 => 'five'
3 => 'height'

希望這能有所幫助...
zoolyka at gmail dot com
6 年前
如果你需要對具有唯一值的陣列進行交集運算,那麼使用 array_intersect_key 的速度大約會快 20 倍,只需將陣列的鍵值對翻轉,然後再將結果翻轉回來即可。

<?php

$one
= range(1, 250000);
$two = range(50000, 150000);

$start = microtime(true);

$intersection = array_intersect($one, $two);

echo
"耗時 ".( microtime(true) - $start )." 秒。\n";

$start = microtime(true);

$intersection = array_flip(array_intersect_key(array_flip($one), array_flip($two)));

echo
"耗時 ".( microtime(true) - $start )." 秒。\n";

?>

耗時 0.89163708686829 秒。
耗時 0.038213968276978 秒。
info at iridsystem dot it
9 年前
這個函式可以根據另一個包含出現順序的陣列來排序一個陣列。不存在的值將被轉移到結果的末尾。
此函式允許根據第二個陣列 ($base) 中包含的值對一個陣列 ($tosort) 的值進行排序,找不到的值將被放置在排序結果的末尾,沒有特定的順序。

<?
$base= array('one', 'two', 'three');

$tosort= array('a'=>'two', 'b'=>'three', 'c'=>'five', 'd'=>'one', 'and'=>'four', 'f'=>'one');

uasort($tosort, function($key1, $key2) use ($base) {
$a1=array_search($key1, $base);
$a2=array_search($key2, $base);

if ( $a1===false && $a2===false ) { return 0; }
else if ( $a1===false && $a2 !== false) { return 1; }
else if ( $a1!==false && $a2 === false) {return -1;}

if( $a1 > $a2 ) { return 1; }
else if ( $a1 < $a2 ) { return -1; }
else if ( $a1 == $a2 ) { return 0; }
});
var_dump($tosort);
/*
$tosort 的結果
array
'd' => string 'one' (長度=3)
'f' => string 'one' (長度=3)
'a' => string 'two' (長度=3)
'b' => string 'three' (長度=3)
'c' => string 'five' (長度=6)
'e' => string 'four' (長度=7)

(Note: 原文'e' 應為 'and')
*/
Gabriel
?>

Oto Brglez
15 年前
如果您希望使用空陣列建立交集。那麼交集的結果就是空陣列。

如果您希望更改這個結果。我建議您這樣做。
它只是「忽略」空陣列。在迴圈之前使用第一個陣列。

<?php

$a
= array();
$a[] = 1;
$a[] = 2;
$a[] = 3;

$b = array();
$b[] = 4;
$b[] = 5;
$b[] = 1;

$c = array();
$c[] = 1;
$c[] = 5;
$d = array();

$kb=array('a','b','c','d');

$out = $a;
foreach(
$kb as $k){
if(!empty(${
$k})) $out = array_intersect($out,${$k});
};
print_r($out);
// 結果是一個陣列

// 結果是一個空陣列
print_r(array_intersect($a,$b,$c,$d));

?>
terry(-at-)shuttleworths(-dot-)net
18 年前
我無法讓 array_intersect 處理兩個包含相同物件的陣列,所以我這樣做:

foreach ($firstarray as $key=>$value){
if (!in_array($value,$secondarray)){
unset($firstarray[$key]);
}
}

這樣 $firstarray 就會變成交集的結果。

看起來運作良好且速度合理。
tom p
19 年前
如果你將一串鍵值儲存在資料庫欄位中,並且想要將它們與一個靜態的值陣列匹配,這是一個無需迴圈即可快速完成的方法:

<?

$vals = array("Blue","Green","Pink","Yellow");
$db_field = "0,2,3";

echo implode(", ", array_flip(array_intersect(array_flip($vals), explode(",", $db_field))));

// 會輸出 "Blue, Pink, Yellow"

?>
ben at kazez dot com
20 年前
要檢查陣列 $a 是否為陣列 $b 的子集,請執行以下操作:

<?php
if(array_unique($b + $a) === $b)
//...
?>

實際上,PHP 應該要有一個函式來幫你做到這一點。但上面的例子可以運作。
karl at libsyn dot com
15 年前
給定一個表示 AND/OR 關係的多維陣列(如下例所示),您可以使用帶有 array_intersect() 的遞迴函式來查看另一個陣列是否符合這組關係。

例如:array( array( 'red' ), array( 'white', 'blue' ) ) 代表 "紅色 或 ( 白色 且 藍色 )"。順帶一提,array( 'red', array( 'white', 'blue' ) ) 也可以運作。

如果我有 array( 'red' ) 想要看看它是否符合 AND/OR 陣列,我會使用以下函式。它會返回符合的陣列,
但如果只需要布林值,它也可以只返回布林值。

<?php
$needle
= array( array( 'red' ), array( 'white', 'blue' ) );
$haystack = array( 'red' );

function
findMatchingArray( $needle, $haystack ) {
foreach(
$needle as $element ) {
$test_element = (array) $element;
if(
count( $test_element ) == count( array_intersect( $test_element, $haystack ) ) ) {
return
$element;
}

}
return
false;
}
?>

很難描述我需要的功能,但它確實有效。我不知道是否還有其他人需要這樣的東西,但希望這能有所幫助。
anbolb at boltblue dot com
20 年前
這也適用於測試陣列是否包含一系列可接受的元素之一。舉一個簡單的例子,如果您預期查詢字串包含 user_id、order_id 或 item_id 其中之一,要找出是哪一個,您可以這樣做:

<?php
$valid_ids
= array ('user_id', 'item_id', 'order_id');
if (
$id = current (array_intersect ($valid_ids, array_keys ($_GET))))
{
// 使用它執行一些操作
}
else
// 錯誤 - 傳遞了無效的 ID,或根本沒有傳遞 ID
?>

……這對於建構 SQL 查詢或其他逐一測試它們可能太過笨拙的情況可能很有用。
Ehsan.Chavoshi.com
5 年前
我寫了這個函式來遞迴地用陣列值替換陣列鍵 (翻轉) 並用定義的值填充值。它可以用於遞迴陣列交集函式。

<?php
函式 array_values_to_keys_r($array, $fill_value = null)
{
$flipped = [];
foreach (
$array as $key => $value) {
if (
is_array($value)) {
$flipped [$key] = array_values_to_keys_r($value);
} else {
$flipped [$value] = $fill_value;
}
}
return
$flipped;
}
?>
david at audiogalaxy dot com
23 年前
需要注意的是,`array_intersect()` 函式在比較陣列元素時會考慮其類型。

如果 `array_intersect()` 函式看起來沒有正常運作,請使用 `var_dump()` 檢查您的輸入,以確保您沒有嘗試將一個整數陣列與一個字串陣列進行交集。
caffinated
12 年前
如果您正在尋找一種相對簡單的方法,可以在不重新排序陣列鍵值的情況下,遞迴地嚴格交集鍵值,這裡有一個簡單的遞迴函式:

<?php
函式 array_intersect_recursive($array1, $array2)
{
foreach(
$array1 as $key => $value)
{
if (!isset(
$array2[$key]))
{
unset(
$array1[$key]);
}
else
{
if (
is_array($array1[$key]))
{
$array1[$key] = array_intersect_recursive($array1[$key], $array2[$key]);
}
elseif (
$array2[$key] !== $value)
{
unset(
$array1[$key]);
}
}
}
return
$array1;
}
?>
gary
15 年前
我寫了這個函式來解決我遇到的問題,因為 PHP 中沒有內建函式可以對字串進行交集,而不是陣列。

<?php
函式 matched_main_numbers($string, $string2)
{
$string = "04 16 17 20 29";
$arr1 = explode(" ", $string);

$string2 = "45 34 04 29 16";
$arr2 = explode(" ", $string2);

$array = array_intersect($arr1, $arr2);
$comma_separated = implode($array);

$str = $comma_separated;

$balls = "$comma_separated";
$matched_balls = chunk_split($balls,2," ");
$matched_balls =" $matched_balls";

$number_of_matched_main_balls = strlen($str);
$number_of_matched_main_balls = ($number_of_matched_main_balls/2);
$numbers = "您匹配了 $number_of_matched_main_balls 個主要球號";

回傳
$numbers;

}
?>
meihao at 126 dot com
11 年前
<?php
$a
=陣列(1,2,'3',4);
$b=陣列('1',2,3);

var_dump($a,$b);

結果:
陣列 (
大小=3)
0 => 整數 1
1
=> 整數 2
2
=> 字串 '3' (長度=1)

?>
Alessandro Ranellucci alex at primafila dot net
21 年前
array_intersect($array1, $array2);
返回的結果與
array_diff($array1, array_diff($array1, $array2));
相同
14 年前
189780 at gmail dot com

<?php
函式 my_array_intersect($a,$b)
{
for(
$i=0;$i<sizeof($a);$i++)
{
$m[]=$a[$i];
}
for(
$i=0;$i<sizeof($a);$i++)
{
$m[]=$b[$i];
}
sort($m);
$get=array();
for(
$i=0;$i<sizeof($m);$i++)
{
if(
$m[$i]==$m[$i+1])
$get[]=$m[$i];
}
return
$get;
}
?>

Barış ÇUHADAR
189780@gmail.com
Mike Block
11 年前
我對 array_intersect 的一些用法進行了基準測試,不敢相信它竟然這麼慢。這個方法雖然沒有那麼精細,但可以處理大多數情況,而且速度要快得多。

<?php
/**
檢查兩個陣列,並返回具有匹配鍵的交集陣列(忽略重複鍵)
*/
函式 simple_array_intersect($a,$b) {
$a_assoc = $a != array_values($a);
$b_assoc = $b != array_values($b);
$ak = $a_assoc ? array_keys($a) : $a;
$bk = $b_assoc ? array_keys($b) : $b;
$out = array();
for (
$i=0;$i<sizeof($ak);$i++) {
if (
in_array($ak[$i],$bk)) {
if (
$a_assoc) {
$out[$ak[$i]] = $a[$ak[$i]];
} else {
$out[] = $ak[$i];
}
}
}
return
$out;
}

?>

您可以試試看這個

<?php
// 建立一個大的陣列(簡單索引)
$first = array();
for (
$i=500;$i<500000;$i++) {
$first[] = $i;
}
// 建立一個小的陣列(關聯式索引)
$second = array();
for (
$i=499990;$i<500000;$i++) {
$second[$i] = rand();
}
echo
microtime(true)."\n";
// 內建函式
print_r(array_intersect($first,$second));
echo
microtime(true)."\n";
// 優先以簡單索引陣列比對
print_r(simple_array_intersect($first,$second));
echo
microtime(true)."\n";
// 優先以關聯式索引比對
print_r(simple_array_intersect($second,$first));
echo
microtime(true)."\n";

?>
ram
6 年前
$x = array('ram@hb.in', 'ram', 'rams@hb.in');
$y = array('1231231231');
$result=array_intersect($x,$z);
$res = array_intersect($y, $z);
To Top