回答:
ここに別の方法があります。中間変数は保存されません。
これを使用して、さまざまな重複するクエリからの結果の重複を排除しました。
$input = array_map("unserialize", array_unique(array_map("serialize", $input)));
serialize(array('a' => '1', 'b' => '1'))
は異なることに注意してくださいserialize(array('b' => '1', 'a' => '1'))
。このオプションは、sets
またはとして使用されるアレイでは失敗します(hash)maps
。
5.2.9以降でarray_unique()
は、SORT_REGULAR
フラグを次のように使用すれば使用できます。
array_unique($array, SORT_REGULAR);
これにより、関数は要素が等しいかどうか$a == $b
を、まるで使用されているかのように比較します。これは、ケースに最適です。
出力
Array
(
[0] => Array
(
[0] => abc
[1] => def
)
[1] => Array
(
[0] => ghi
[1] => jkl
)
[2] => Array
(
[0] => mno
[1] => pql
)
)
array_unique()
多次元配列で動作するようには設計されていません。
同様の問題がありましたが、100%有効な解決策を見つけました。
<?php
function super_unique($array,$key)
{
$temp_array = [];
foreach ($array as &$v) {
if (!isset($temp_array[$v[$key]]))
$temp_array[$v[$key]] =& $v;
}
$array = array_values($temp_array);
return $array;
}
$arr="";
$arr[0]['id']=0;
$arr[0]['titel']="ABC";
$arr[1]['id']=1;
$arr[1]['titel']="DEF";
$arr[2]['id']=2;
$arr[2]['titel']="ABC";
$arr[3]['id']=3;
$arr[3]['titel']="XYZ";
echo "<pre>";
print_r($arr);
echo "unique*********************<br/>";
print_r(super_unique($arr,'titel'));
?>
別の方法。キーも保持します。
function array_unique_multidimensional($input)
{
$serialized = array_map('serialize', $input);
$unique = array_unique($serialized);
return array_intersect_key($input, $unique);
}
array_unique()ドキュメントに関するユーザーのコメントには、これに対する多くの解決策があります。以下はその1つです。
kennsnsn at rbnsn dot com
27-Sep-2005 12:09マルチディメンション化された配列のためのさらに別のArray_Unique。私はこれを2次元の配列でのみテストしましたが、多分一般化するか、再帰を使用するようにすることができます。
この関数は、serialize、array_unique、およびunserialize関数を使用して作業を行います。
function multi_unique($array) { foreach ($array as $k=>$na) $new[$k] = serialize($na); $uniq = array_unique($new); foreach($uniq as $k=>$ser) $new1[$k] = unserialize($ser); return ($new1); }
これはhttp://ca3.php.net/manual/en/function.array-unique.php#57202からです。
「重複を削除する」が「重複を削除するが、1つは許可する」を意味する場合、解決策はarray_unique(...)
まず「識別子列」にを適用し、次に列配列から削除されたすべてのキーを元の配列で削除することです。 :
$array = [
[
'id' => '123',
'foo' => 'aaa',
'bar' => 'bbb'
],
[
'id' => '123',
'foo' => 'ccc',
'bar' => 'ddd'
],
[
'id' => '567',
'foo' => 'eee',
'bar' => 'fff'
]
];
$ids = array_column($array, 'id');
$ids = array_unique($ids);
$array = array_filter($array, function ($key, $value) use ($ids) {
return in_array($value, array_keys($ids));
}, ARRAY_FILTER_USE_BOTH);
結果は次のとおりです。
Array
(
[0] => Array
(
[id] => 123
[foo] => aaa
[bar] => bbb
)
[2] => Array
(
[id] => 567
[foo] => eee
[bar] => fff
)
)
Array
(
[0] => Array
(
[id] => 1
[name] => john
)
[1] => Array
(
[id] => 2
[name] => smith
)
[2] => Array
(
[id] => 3
[name] => john
)
[3] => Array
(
[id] => 4
[name] => robert
)
)
$temp = array_unique(array_column($array, 'name'));
$unique_arr = array_intersect_key($array, $temp);
これにより、重複した名前が配列から削除されます。キーによって一意
$array
キーが「0」で始まることを確認してください。が前の配列操作の結果である$array
場合、のキーが別の番号で始まる可能性$array
があります。array_values
キーを「0」にリセットするために使用します
2番目のパラメーターとしてSORT_REGULARオプションを使用するだけです。
$uniqueArray = array_unique($array, SORT_REGULAR);
多次元配列を一意にする非常に簡単で論理的な方法は次のとおりです。
次のような配列がある場合:
Array
(
[Key1] => Array
(
[0] => Value1
[1] => Value2
[2] => Value1
[3] => Value3
[4] => Value1
)
[Key2] => Array
(
[0] => Value1
[1] => Value2
[2] => Value1
[3] => Value3
[4] => Value4
)
)
foreach
これを解決するために使用:
foreach($array as $k=>$v){
$unique=array_unique($v);
$array[$k]=$unique;
}
次の結果が得られます。
Array
(
[Key1] => Array
(
[0] => Value1
[1] => Value2
[3] => Value3
)
[Key2] => Array
(
[0] => Value1
[1] => Value2
[3] => Value3
[4] => Value4
)
)
キーの順序を変更したい場合は、
foreach($array as $k=>$v){
$unique= array_values(array_unique($v));
$array[$k]=$unique;
}
この操作により、次のように配置されたキー値が得られます。
Array
(
[Key1] => Array
(
[0] => Value1
[1] => Value2
[2] => Value3
)
[Key2] => Array
(
[0] => Value1
[1] => Value2
[2] => Value3
[3] => Value4
)
)
これですべてがクリアされることを願っています。
次のような配列がある場合:
(usersはアレイの名前です)
Array=>
[0] => (array)
'user' => 'john'
'age' => '23'
[1] => (array)
'user' => 'jane'
'age' => '20'
[2]=> (array)
'user' => 'john'
'age' => '23'
そしてあなたは重複を削除したい...その後:
$serialized = array();
for ($i=0; $i < sizeof($users); $i++) {
$test = in_array($users['user'], $serialized);
if ($test == false) {
$serialized[] = $users['user'];
}
}
ソリューションにすることができます:P
人々がarray_unique()
非常に遅いと言っているように、これが私が1レベルの多次元配列に使用するスニペットです。
$serialized_array = array_map("serialize", $input);
foreach ($serialized_array as $key => $val) {
$result[$val] = true;
}
$output = array_map("unserialize", (array_keys($result)));
$output = array_map('unserialize', array_keys($result));
多くの人から、Unique多次元配列の作り方を尋ねられました。私はあなたのコメントから参照を取りました、そしてそれは私を助けます。
まず第一に、あなたの解決のために@jeromegamez @daveilersに感謝します。しかし、答えを出すたびに、この「シリアライズ」と「アンシリアライズ」がどのように機能するかを尋ねられました。その理由を私はあなたと共有して、より多くの人々がこの背後にある概念を理解するのに役立つようにしたいと思います。
なぜ 'serialize'と 'unserialize'を段階的に使うのかを説明しています:
ステップ1:多次元配列を1次元配列に変換する
多次元配列を1次元配列に変換するには、まず配列内のすべての要素(ネストされた配列を含む)のバイトストリーム表現を生成します。serialize()関数は、値のバイトストリーム表現を生成できます。すべての要素のバイトストリーム表現を生成するには、array_map()関数内のserialize()関数をコールバック関数として呼び出します。結果は、多次元配列のレベル数に関係なく、1次元配列になります。
ステップ2:値を一意にする
この1次元配列を一意にするには、array_unique()関数を使用します。
ステップ3:多次元配列に戻す
配列は一意になりましたが、値はバイトストリーム表現のように見えます。多次元配列に戻すには、unserialize()関数を使用します。
$input = array_map("unserialize", array_unique(array_map("serialize", $input)));
本当にありがとうございました。
シリアル化および一意化の代替手段
$test = [
['abc','def'],
['ghi','jkl'],
['mno','pql'],
['abc','def'],
['ghi','jkl'],
['mno','pql'],
];
$result = array_reduce(
$test,
function($carry,$item){
if(!in_array($item,$carry)) {
array_push($carry,$item);
}
return $carry;
},
[]
);
var_dump($result);
/*
php unique.php
array(3) {
[0] =>
array(2) {
[0] =>
string(3) "abc"
[1] =>
string(3) "def"
}
[1] =>
array(2) {
[0] =>
string(3) "ghi"
[1] =>
string(3) "jkl"
}
[2] =>
array(2) {
[0] =>
string(3) "mno"
[1] =>
string(3) "pql"
}
}
* /
このような配列がある場合
data = array
(
[0] => array
(
[subject] => a
[object] => c
),
[1] => array
(
[subject] => b
[object] => d
),
[2] => array
(
[subject] => d
[object] => b
),
[3] => array
(
[subject] => d
[object] => c
),
[4] => array
(
[subject] => c
[object] => a
),
[5] => array
(
[subject] => c
[object] => d
)
)
そして、あなたはこのような配列を得たいです:
data = array
(
[0] => array
(
[subject] => a
[object] => c
),
[1] => array
(
[subject] => b
[object] => d
),
[2] => array
(
[subject] => d
[object] => c
)
)
または
data = array
(
[0] => array
(
[subject] => d
[object] => b
),
[1] => array
(
[subject] => c
[object] => a
),
[2] => array
(
[subject] => c
[object] => d
)
)
次のコードが役立ちます
$data1 = array();
$data1 = $data;
for($q=0;$q<count($data);$q++)
{
for($p=0;$p<count($data1);$p++)
{
if (($data[$q]["subject"] == $data1[$p]["object"]) && ($data[$q]["object"] == $data1[$p]["subject"]))
{
$data1[$p]["subject"] = $data[$q]["subject"];
$data1[$p]["object"] = $data[$q]["object"];
}
}
}
$data1 = array_values(array_map("unserialize", array_unique(array_map("serialize", $data1))));
$data = $data1;
私はこの問題をよく考え、最適なソリューションは2つのルールに従う必要があると判断しました。
これを念頭に置き、PHPの癖をすべて踏まえて、以下に私が考え出したソリューションを示します。他のいくつかの回答とは異なり、必要なキーに基づいて要素を削除する機能があります。入力配列は数値キーであることが期待されています。
$count_array = count($input);
for ($i = 0; $i < $count_array; $i++) {
if (isset($input[$i])) {
for ($j = $i+1; $j < $count_array; $j++) {
if (isset($input[$j])) {
//this is where you do your comparison for dupes
if ($input[$i]['checksum'] == $input[$j]['checksum']) {
unset($input[$j]);
}
}
}
}
}
唯一の欠点は、反復が完了したときにキーの順序が正しくないことです。後でforeachループのみを使用する場合は問題ありませんが、forループを使用する必要がある場合は$input = array_values($input);
、上記の後に配置してキーの番号を付け直すことができます。