PHPのお勉強!

PHP TOP

array_unique

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

array_unique配列から重複した値を削除する

説明

array_unique(array $array, int $flags = SORT_STRING): array

array を入力とし、値に重複のない新規配列を返します。

キーは保持されることに注意してください。 指定された flags において、 複数の要素が等しかった場合、はじめの要素のキーと値が保持されます。

注意: (string) $elem1 === (string) $elem2 の場合のみ二つの要素は等しいとみなされます。 つまり、文字列表現が同じである場合は、最初の要素を使用します。

パラメータ

array

入力の配列。

flags

オプションの 2 番目のパラメータ flags にこれらの値を使用して、比較の挙動を変更します。

比較形式のフラグは次のとおりです。

戻り値

処理済の配列を返します。

変更履歴

バージョン 説明
7.2.0 flagsSORT_STRING の場合、 新しい配列が生成され、ユニークな要素が追加されるようになりました。 これによって、異なった数値のインデックスが振られる可能性があります。 これより前のバージョンでは、 array がコピーされ、 (配列を後にパックせずに) ユニークでない値が削除されていました。

例1 array_unique() の例

<?php
$input
= array("a" => "green", "red", "b" => "green", "blue", "red");
$result = array_unique($input);
print_r($result);
?>

上の例の出力は以下となります。

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

例2 array_unique() と型

<?php
$input
= array(4, "4", "3", 4, 3, "3");
$result = array_unique($input);
var_dump($result);
?>

上の例の出力は以下となります。

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

注意

注意: array_unique() は、 多次元配列での使用を想定したものではないことに注意しましょう。

参考

add a note

User Contributed Notes 33 notes

up
317
Ghanshyam Katriya(anshkatriya at gmail)
10 years ago
Create multidimensional array unique for any single key index.
e.g I want to create multi dimentional unique array for specific code

Code :
My array is like this,

<?php
$details
= array(
0 => array("id"=>"1", "name"=>"Mike", "num"=>"9876543210"),
1 => array("id"=>"2", "name"=>"Carissa", "num"=>"08548596258"),
2 => array("id"=>"1", "name"=>"Mathew", "num"=>"784581254"),
);
?>

You can make it unique for any field like id, name or num.

I have develop this function for same :
<?php
function unique_multidim_array($array, $key) {
$temp_array = array();
$i = 0;
$key_array = array();

foreach(
$array as $val) {
if (!
in_array($val[$key], $key_array)) {
$key_array[$i] = $val[$key];
$temp_array[$i] = $val;
}
$i++;
}
return
$temp_array;
}
?>

Now, call this function anywhere from your code,

something like this,
<?php
$details
= unique_multidim_array($details,'id');
?>

Output will be like this :
<?php
$details
= array(
0 => array("id"=>"1","name"=>"Mike","num"=>"9876543210"),
1 => array("id"=>"2","name"=>"Carissa","num"=>"08548596258"),
);
?>
up
30
Mike D. - michal at euro-net.pl
2 years ago
modified code originally posted by Ghanshyam Katriya(anshkatriya at gmail) [highest voted comment here].

1. In php 7.4 counter $i breaks the function. Removed completely (imo was waste of keystrokes anyway).
2. I added second return value - array of duplicates. So you can take both and compare them (I had to).

Example array (copy-paste from original post):
<?php
$details
= array(
0 => array("id"=>"1", "name"=>"Mike", "num"=>"9876543210"),
1 => array("id"=>"2", "name"=>"Carissa", "num"=>"08548596258"),
2 => array("id"=>"1", "name"=>"Mathew", "num"=>"784581254"),
);
?>

Function:
<?php
function unique_multidim_array($array, $key) : array {
$uniq_array = array();
$dup_array = array();
$key_array = array();

foreach(
$array as $val) {
if (!
in_array($val[$key], $key_array)) {
$key_array[] = $val[$key];
$uniq_array[] = $val;
/*
# 1st list to check:
# echo "ID or sth: " . $val['building_id'] . "; Something else: " . $val['nodes_name'] . (...) "\n";
*/
} else {
$dup_array[] = $val;
/*
# 2nd list to check:
# echo "ID or sth: " . $val['building_id'] . "; Something else: " . $val['nodes_name'] . (...) "\n";
*/
}
}
return array(
$uniq_array, $dup_array, /* $key_array */);
}
?>

Usage:
<?php
list($unique_addresses, $duplicates, /* $unique_keys */) = unique_multidim_array($details,'id');
?>

Then:
var_dump($unique_addresses);
or
var_dump($duplicates);
or foreach or whatever. Personally I just echo-ed 1st and then 2nd (both DOUBLE COMMENTED) list in function itself (then copied both to notepad++ and compared them - just to be 100% sure), but in case you want to do something else with it - enjoy :)
Plus - as a bonus - you also get an array of UNIQUE keys you searched for (just uncomment >$key_array< in both: function return and function call code).

From example array code returns:
var_dump($unique_addresses);
array(2) {
[0]=>
array(3) {
["id"]=>
string(1) "1"
["name"]=>
string(4) "Mike"
["num"]=>
string(10) "9876543210"
}
[1]=>
array(3) {
["id"]=>
string(1) "2"
["name"]=>
string(7) "Carissa"
["num"]=>
string(11) "08548596258"
}
}

var_dump($duplicates);
array(1) {
[0]=>
array(3) {
["id"]=>
string(1) "1"
["name"]=>
string(6) "Mathew"
["num"]=>
string(9) "784581254"
}
}

Plus keys, if you want.

P.S.: in my - practical - case of DB querying I got around 4k uniques and 15k dupes :)
up
23
falundir at gmail dot com
6 years ago
I find it odd that there is no version of this function which allows you to use a comparator callable in order to determine items equality (like array_udiff and array_uintersect). So, here's my version for you:

<?php
function array_uunique(array $array, callable $comparator): array {
$unique_array = [];
do {
$element = array_shift($array);
$unique_array[] = $element;

$array = array_udiff(
$array,
[
$element],
$comparator
);
} while (
count($array) > 0);

return
$unique_array;
}
?>

And here is a test code:

<?php
class Foo {

public
$a;

public function
__construct(int $a) {
$this->a = $a;
}
}

$array_of_objects = [new Foo(2), new Foo(1), new Foo(3), new Foo(2), new Foo(2), new Foo(1)];

$comparator = function (Foo $foo1, Foo $foo2): int {
return
$foo1->a <=> $foo2->a;
};

var_dump(array_uunique($array_of_objects, $comparator)); // should output [Foo(2), Foo(1), Foo(3)]
?>
up
96
Anonymous
14 years ago
It's often faster to use a foreache and array_keys than array_unique:

<?php

$max
= 1000000;
$arr = range(1,$max,3);
$arr2 = range(1,$max,2);
$arr = array_merge($arr,$arr2);

$time = -microtime(true);
$res1 = array_unique($arr);
$time += microtime(true);
echo
"deduped to ".count($res1)." in ".$time;
// deduped to 666667 in 32.300781965256

$time = -microtime(true);
$res2 = array();
foreach(
$arr as $key=>$val) {
$res2[$val] = true;
}
$res2 = array_keys($res2);
$time += microtime(true);
echo
"<br />deduped to ".count($res2)." in ".$time;
// deduped to 666667 in 0.84372591972351

?>
up
20
stoff@
7 years ago
In reply to performance tests array_unique vs foreach.

In PHP7 there were significant changes to Packed and Immutable arrays resulting in the performance difference to drop considerably. Here is the same test on php7.1 here;
http://sandbox.onlinephpfunctions.com/code/2a9e986690ef8505490489581c1c0e70f20d26d1

$max = 770000; //large enough number within memory allocation
$arr = range(1,$max,3);
$arr2 = range(1,$max,2);
$arr = array_merge($arr,$arr2);

$time = -microtime(true);
$res1 = array_unique($arr);
$time += microtime(true);
echo "deduped to ".count($res1)." in ".$time;
// deduped to 513333 in 1.0876770019531

$time = -microtime(true);
$res2 = array();
foreach($arr as $key=>$val) {
$res2[$val] = true;
}
$res2 = array_keys($res2);
$time += microtime(true);
echo "<br />deduped to ".count($res2)." in ".$time;
// deduped to 513333 in 0.054931879043579
up
3
calexandrepcjr at gmail dot com
7 years ago
Following the Ghanshyam Katriya idea, but with an array of objects, where the $key is related to object propriety that you want to filter the uniqueness of array:

<?php
function obj_multi_unique($obj, $key = false)
{
$totalObjs = count($obj);
if (
is_array($obj) && $totalObjs > 0 && is_object($obj[0]) && ($key && !is_numeric($key))) {
for (
$i = 0; $i < $totalObjs; $i++) {
if (isset(
$obj[$i])) {
for (
$j = $i + 1; $j < $totalObjs; $j++) {
if (isset(
$obj[$j]) && $obj[$i]->{$key} === $obj[$j]->{$key}) {
unset(
$obj[$j]);
}
}
}
}
return
array_values($obj);
} else {
throw new
Exception('Invalid argument or your array of objects is empty');
}
}
?>
up
26
Ray dot Paseur at SometimesUsesGmail dot com
16 years ago
I needed to identify email addresses in a data table that were replicated, so I wrote the array_not_unique() function:

<?php

function array_not_unique($raw_array) {
$dupes = array();
natcasesort($raw_array);
reset ($raw_array);

$old_key = NULL;
$old_value = NULL;
foreach (
$raw_array as $key => $value) {
if (
$value === NULL) { continue; }
if (
$old_value == $value) {
$dupes[$old_key] = $old_value;
$dupes[$key] = $value;
}
$old_value = $value;
$old_key = $key;
}
return
$dupes;
}

$raw_array = array();
$raw_array[1] = 'abc@xyz.com';
$raw_array[2] = 'def@xyz.com';
$raw_array[3] = 'ghi@xyz.com';
$raw_array[4] = 'abc@xyz.com'; // Duplicate

$common_stuff = array_not_unique($raw_array);
var_dump($common_stuff);
?>
up
2
free dot smilesrg at gmail dot com
2 years ago
$a = new StdClass();
$b = new StdClass();

var_dump(array_unique([$a, $b, $b, $a], SORT_REGULAR));
//array(1) {
// [0]=>
// object(stdClass)#1 (0) {
// }
//}

$a->name = 'One';
$b->name = 'Two';

var_dump(array_unique([$a, $b, $b, $a], SORT_REGULAR));

//array(2) {
// [0]=>
// object(stdClass)#1 (1) {
// ["name"]=>
// string(3) "One"
// }
// [1]=>
// object(stdClass)#2 (1) {
// ["name"]=>
// string(3) "Two"
// }
//}
up
2
contact at evoweb dot fr
3 years ago
Here is a solution to make unique values keeping empty values for an array with keys :

<?php
function array_unique_kempty($array) {
$values = array_unique($array);
$return = array_combine(array_keys($array), array_fill(0,count($array),null));
return
array_merge($return,$values);
}

$myArray = [
"test1" => "aaa",
"test2" => null,
"test3" => "aaa",
"test4" => "bbb",
"test5" => null,
"test6" => "ccc",
"test7" => "ddd",
"test8" => "ccc"
];

echo
"<pre>".print_r(array_unique_kempty($myArray),true)."</pre>";

/*
Array
(
[test1] => aaa
[test2] =>
[test3] =>
[test4] => bbb
[test5] =>
[test6] => ccc
[test7] => ddd
[test8] =>
)
*/
?>
up
36
mnbayazit
17 years ago
Case insensitive; will keep first encountered value.

<?php

function array_iunique($array) {
$lowered = array_map('strtolower', $array);
return
array_intersect_key($array, array_unique($lowered));
}

?>
up
2
PHP Expert
16 years ago
Case insensitive for PHP v4.x and up.

<?php

function in_iarray($str, $a) {
foreach (
$a as $v) {
if (
strcasecmp($str, $v) == 0) {
return
true;
}
}
return
false;
}

function
array_iunique($a) {
$n = array();
foreach (
$a as $k => $v) {
if (!
in_iarray($v, $n)) {
$n[$k]=$v;
}
}
return
$n;
}

$input = array("aAa","bBb","cCc","AaA","ccC","ccc","CCC","bBB","AAA","XXX");
$result = array_iunique($input);
print_r($result);

/*
Array
(
[0] => aAa
[1] => bBb
[2] => cCc
[9] => XXX
)
*/
?>
up
6
sashasimkin at gmail dot com
12 years ago
My object unique function:

<?php
function object_unique( $obj ){
$objArray = (array) $obj;

$objArray = array_intersect_assoc( array_unique( $objArray ), $objArray );

foreach(
$obj as $n => $f ) {
if( !
array_key_exists( $n, $objArray ) ) unset( $obj->$n );
}

return
$obj;
}
?>

And these code:

<?php
class Test{
public
$pr0 = 'string';
public
$pr1 = 'string1';
public
$pr2 = 'string';
public
$pr3 = 'string2';
}

$obj = new Test;

var_dump( object_unique( $obj ) );
?>

returns:
object(Test)[1]
public 'pr0' => string 'string' (length=6)
public 'pr1' => string 'string1' (length=7)
public 'pr3' => string 'string2' (length=7)
up
1
Victoire Nkolo at crinastudio.com
1 year ago
<?php

//removes duplicated objetcs from an array according to the property given

class ArrayFilter
{

public static function
dedupe_array_of_objets(array $array, string $property) : array
{
$i = 0;
$filteredArray = array();
$keyArray = array();

foreach(
$array as $item) {
if (!
in_array($item->$property, $keyArray)) {
$keyArray[$i] = $item->$property;
$filteredArray[$i] = $item;
}
$i++;
}
return
$filteredArray;
}
}
up
16
mostafatalebi at rocketmail dot com
11 years ago
If you find the need to get a sorted array without it preserving the keys, use this code which has worked for me:

<?php

$array
= array("hello", "fine", "good", "fine", "hello", "bye");

$get_sorted_unique_array = array_values(array_unique($array));

?>

The above code returns an array which is both unique and sorted from zero.