PHP:在数组的数组上使用 array_unique?

发布于 2024-08-27 08:48:17 字数 952 浏览 7 评论 0原文

我有一个数组,

Array(
[0] => Array
    (
        [0] => 33
        [user_id] => 33
        [1] => 3
        [frame_id] => 3
    )

[1] => Array
    (
        [0] => 33
        [user_id] => 33
        [1] => 3
        [frame_id] => 3
    )

[2] => Array
    (
        [0] => 33
        [user_id] => 33
        [1] => 8
        [frame_id] => 8
    )

[3] => Array
    (
        [0] => 33
        [user_id] => 33
        [1] => 3
        [frame_id] => 3
    )

[4] => Array
    (
        [0] => 33
        [user_id] => 33
        [1] => 3
        [frame_id] => 3
    )

)

如您所见,键 0 与 1、3 和 4 相同。键 2 与它们都不同。

当在它们上运行 array_unique 函数时,唯一剩下的是“

Array (
[0] => Array
    (
        [0] => 33
        [user_id] => 33
        [1] => 3
        [frame_id] => 3
    )
)

有什么想法为什么 array_unique 不能按预期工作吗?”

I have an array

Array(
[0] => Array
    (
        [0] => 33
        [user_id] => 33
        [1] => 3
        [frame_id] => 3
    )

[1] => Array
    (
        [0] => 33
        [user_id] => 33
        [1] => 3
        [frame_id] => 3
    )

[2] => Array
    (
        [0] => 33
        [user_id] => 33
        [1] => 8
        [frame_id] => 8
    )

[3] => Array
    (
        [0] => 33
        [user_id] => 33
        [1] => 3
        [frame_id] => 3
    )

[4] => Array
    (
        [0] => 33
        [user_id] => 33
        [1] => 3
        [frame_id] => 3
    )

)

As you can see key 0 is the same as 1, 3 and 4. And key 2 is different from them all.

When running the array_unique function on them, the only left is

Array (
[0] => Array
    (
        [0] => 33
        [user_id] => 33
        [1] => 3
        [frame_id] => 3
    )
)

Any ideas why array_unique isn't working as expected?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

携余温的黄昏 2024-09-03 08:48:17

这是因为 array_unique 使用字符串比较来比较项目。来自 文档

注意:考虑两个元素
等于当且仅当(字符串)$elem1
===(字符串)$elem2。换句话说:当字符串表示相同时。
将使用第一个元素。

数组的字符串表示形式就是单词Array,无论其内容是什么。

您可以通过使用以下命令来完成您想做的事情:

$arr = array(
    array('user_id' => 33, 'frame_id' => 3),
    array('user_id' => 33, 'frame_id' => 3),
    array('user_id' => 33, 'frame_id' => 8)
);

$arr = array_intersect_key($arr, array_unique(array_map('serialize', $arr)));

//result:
array
  0 => 
    array
      'user_id' => int 33
      'user' => int 3
  2 => 
    array
      'user_id' => int 33
      'user' => int 8

下面是它的工作原理:

  1. 每个数组项都被序列化。这
    基于数组将是唯一的
    内容。

  2. 其结果通过array_unique运行,
    所以只有具有唯一的数组
    留下签名。

  3. array_intersect_key 将采用
    独特物品的钥匙
    map/unique 函数(因为源数组的键被保留)和 pull
    它们脱离了你的原始来源
    数组。

It's because array_unique compares items using a string comparison. From the docs:

Note: Two elements are considered
equal if and only if (string) $elem1
=== (string) $elem2. In words: when the string representation is the same.
The first element will be used.

The string representation of an array is simply the word Array, no matter what its contents are.

You can do what you want to do by using the following:

$arr = array(
    array('user_id' => 33, 'frame_id' => 3),
    array('user_id' => 33, 'frame_id' => 3),
    array('user_id' => 33, 'frame_id' => 8)
);

$arr = array_intersect_key($arr, array_unique(array_map('serialize', $arr)));

//result:
array
  0 => 
    array
      'user_id' => int 33
      'user' => int 3
  2 => 
    array
      'user_id' => int 33
      'user' => int 8

Here's how it works:

  1. Each array item is serialized. This
    will be unique based on the array's
    contents.

  2. The results of this are run through array_unique,
    so only arrays with unique
    signatures are left.

  3. array_intersect_key will take
    the keys of the unique items from
    the map/unique function (since the source array's keys are preserved) and pull
    them out of your original source
    array.

风月客 2024-09-03 08:48:17

这是 @ryeguy 的答案的改进版本:

<?php

$arr = array(
    array('user_id' => 33, 'tmp_id' => 3),
    array('user_id' => 33, 'tmp_id' => 4),
    array('user_id' => 33, 'tmp_id' => 5)
);


# $arr = array_intersect_key($arr, array_unique(array_map('serialize', $arr)));
$arr = array_intersect_key($arr, array_unique(array_map(function ($el) {
    return $el['user_id'];
}, $arr)));

//result:
array
  0 => 
    array
      'user_id' => int 33
      'tmp_id' => int 3

首先,它不会执行不必​​要的序列化。其次,有时即使 id 相同,属性也可能不同。

这里的技巧是 array_unique() 保留键:

$ php -r 'var_dump(array_unique([1, 2, 2, 3]));'
array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [3]=>
  int(3)
}

这让我们 array_intersect_key() 保留所需的元素。

我在使用 Google Places API 时遇到了这个问题。我将多个请求的结果与不同类型的对象(想想标签)结合起来。但我得到了重复项,因为一个对象可以分为多个类别(类型)。并且 serialize 方法不起作用,因为 attrs 不同,即 photo_referencereference。可能这些就像临时 ID。

Here's an improved version of @ryeguy's answer:

<?php

$arr = array(
    array('user_id' => 33, 'tmp_id' => 3),
    array('user_id' => 33, 'tmp_id' => 4),
    array('user_id' => 33, 'tmp_id' => 5)
);


# $arr = array_intersect_key($arr, array_unique(array_map('serialize', $arr)));
$arr = array_intersect_key($arr, array_unique(array_map(function ($el) {
    return $el['user_id'];
}, $arr)));

//result:
array
  0 => 
    array
      'user_id' => int 33
      'tmp_id' => int 3

First, it doesn't do unneeded serialization. Second, sometimes attributes may be different even so id is the same.

The trick here is that array_unique() preserves the keys:

$ php -r 'var_dump(array_unique([1, 2, 2, 3]));'
array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [3]=>
  int(3)
}

This let's array_intersect_key() leave the desired elements.

I've run into it with Google Places API. I was combining results of several requests with different type of objects (think tags). But I got duplicates, since an object may be put into several categories (types). And the method with serialize didn't work, since the attrs were different, namely, photo_reference and reference. Probably these are like temporary ids.

忘年祭陌 2024-09-03 08:48:17

array_unique() 仅在 PHP 5.2.9 及更高版本中支持多维数组。

相反,您可以创建数组的哈希值并检查其唯一性。

$hashes = array(); 

foreach($array as $val) { 
    $hashes[md5(serialize($val))] = $val; 
} 

array_unique($hashes);

array_unique() only supports multi-dimensional arrays in PHP 5.2.9 and higher.

Instead, you can create a hash of the array and check it for unique-ness.

$hashes = array(); 

foreach($array as $val) { 
    $hashes[md5(serialize($val))] = $val; 
} 

array_unique($hashes);
驱逐舰岛风号 2024-09-03 08:48:17

array_unique deos 不能递归工作,所以它只是认为“这都是数组,让我们杀死除了一个以外的所有数组……开始吧!”

array_unique deosn't work recursive, so it just thinks "this are all Arrays, let's kill all but one... here we go!"

呆橘 2024-09-03 08:48:17

快速回答 (TL;DR)

  • 可以使用 foreach 从 PHP Array of AssociativeArrays 中提取不同的值
  • 这是一种简单化的方法

详细答案

上下文

  • PHP 5.3
  • PHP Array of AssociativeArrays(表格复合数据变量)
  • 该复合变量的替代名称是 ArrayOfDictionary (AOD)

问题

  • 场景:DeveloperMarsher 有一个 PHP 表格复合变量
    • DeveloperMarsher 希望提取特定名称-值对上的不同值
    • 在下面的示例中,DeveloperMarsher 希望获取每个不同 fname 名称-值对的行

解决方案

  • example01 ;; DeveloperMarsher 从一个表格数据变量开始,如下所示

    $aodtable = json_decode('[
    {
      “fname”:“荷马”
      ,"lname": "辛普森"
    },
    {
      “fname”:“荷马”
      ,"lname": "杰克逊"
    },
    {
      “fname”:“荷马”
      ,"lname": "约翰逊"
    },
    {
      “fname”:“巴特”
      ,"lname": "约翰逊"
    },
    {
      “fname”:“巴特”
      ,"lname": "杰克逊"
    },
    {
      “fname”:“巴特”
      ,"lname": "辛普森"
    },
    {
      “fname”:“弗雷德”
      ,"lname": "打火石"
    }
    ]',真的);
    
  • example01 ;; DeveloperMarsher 可以使用跟踪可见值的 foreach 循环提取不同的值

    $sgfield = 'fname';
    $bgnocase = true;
    
    //
    $targfield = $sgfield;
    $ddseen = 数组();
    $vout = 数组();
    foreach ($aodtable as $datarow) {
    if( (boolean) $bgnocase == true ){ @$datarow[$targfield] = @strtolower($datarow[$targfield]); }
    if( (字符串) @$ddseen[ $datarow[$targfield] ] == '' ){
      $rowout = array_intersect_key($datarow, array_flip(array_keys($datarow)));
      $ddseen[ $datarow[$targfield] ] = $datarow[$targfield];
      $vout[] = 数组( $rowout );
    }
    }
    //;;
    
    打印 var_export( $vout, true );
    

输出结果

array (
  0 =>
  array (
    0 =>
    array (
      'fname' => 'homer',
      'lname' => 'simpson',
    ),
  ),
  1 =>
  array (
    0 =>
    array (
      'fname' => 'bart',
      'lname' => 'johnson',
    ),
  ),
  2 =>
  array (
    0 =>
    array (
      'fname' => 'fred',
      'lname' => 'flintstone',
    ),
  ),
)

陷阱

  • 该解决方案不会聚合不属于 DISTINCT 操作的字段
  • 任意选择的不同行返回任意名称-值对
  • 输出的任意排序顺序
  • 任意处理字母大小写(大写 A 与小写 a 不同吗?)

另请参阅

  • php array_intersect_key
  • php array_flip

Quick Answer (TL;DR)

  • Distinct values may be extracted from PHP Array of AssociativeArrays using foreach
  • This is a simplistic approach

Detailed Answer

Context

  • PHP 5.3
  • PHP Array of AssociativeArrays (tabluar composite data variable)
  • Alternate name for this composite variable is ArrayOfDictionary (AOD)

Problem

  • Scenario: DeveloperMarsher has a PHP tabular composite variable
    • DeveloperMarsher wishes to extract distinct values on a specific name-value pair
    • In the example below, DeveloperMarsher wishes to get rows for each distinct fname name-value pair

Solution

  • example01 ;; DeveloperMarsher starts with a tabluar data variable that looks like this

    $aodtable = json_decode('[
    {
      "fname": "homer"
      ,"lname": "simpson"
    },
    {
      "fname": "homer"
      ,"lname": "jackson"
    },
    {
      "fname": "homer"
      ,"lname": "johnson"
    },
    {
      "fname": "bart"
      ,"lname": "johnson"
    },
    {
      "fname": "bart"
      ,"lname": "jackson"
    },
    {
      "fname": "bart"
      ,"lname": "simpson"
    },
    {
      "fname": "fred"
      ,"lname": "flintstone"
    }
    ]',true);
    
  • example01 ;; DeveloperMarsher can extract distinct values with a foreach loop that tracks seen values

    $sgfield  =   'fname';
    $bgnocase =   true;
    
    //
    $targfield  =   $sgfield;
    $ddseen     =   Array();
    $vout       =   Array();
    foreach ($aodtable as $datarow) {
    if( (boolean) $bgnocase == true ){ @$datarow[$targfield] = @strtolower($datarow[$targfield]); }
    if( (string) @$ddseen[ $datarow[$targfield] ] == '' ){
      $rowout   = array_intersect_key($datarow, array_flip(array_keys($datarow)));
      $ddseen[ $datarow[$targfield] ] = $datarow[$targfield];
      $vout[] = Array( $rowout );
    }
    }
    //;;
    
    print var_export( $vout, true );
    

Output result

array (
  0 =>
  array (
    0 =>
    array (
      'fname' => 'homer',
      'lname' => 'simpson',
    ),
  ),
  1 =>
  array (
    0 =>
    array (
      'fname' => 'bart',
      'lname' => 'johnson',
    ),
  ),
  2 =>
  array (
    0 =>
    array (
      'fname' => 'fred',
      'lname' => 'flintstone',
    ),
  ),
)

Pitfalls

  • This solution does not aggregate on fields that are not part of the DISTINCT operation
  • Arbitrary name-value pairs are returned from arbitrarily chosen distinct rows
  • Arbitrary sort order of output
  • Arbitrary handling of letter-case (is capital A distinct from lower-case a ?)

See also

  • php array_intersect_key
  • php array_flip
不顾 2024-09-03 08:48:17
function array_unique_recursive($array)
{
    $array = array_unique($array, SORT_REGULAR);

    foreach ($array as $key => $elem) {
        if (is_array($elem)) {
            $array[$key] = array_unique_recursive($elem);
        }
    }

    return $array;
}

这不就起作用了吗?

function array_unique_recursive($array)
{
    $array = array_unique($array, SORT_REGULAR);

    foreach ($array as $key => $elem) {
        if (is_array($elem)) {
            $array[$key] = array_unique_recursive($elem);
        }
    }

    return $array;
}

Doesn't that do the trick ?

琴流音 2024-09-03 08:48:17
`

    $arr = array(
        array('user_id' => 33, 'tmp_id' => 3),
        array('user_id' => 33, 'tmp_id' => 4),
        array('user_id' => 33, 'tmp_id' => 3),
        array('user_id' => 33, 'tmp_id' => 4),
    );
    $arr1 = array_unique($arr,SORT_REGULAR);
    echo "<pre>";
    print_r($arr1);
    echo "</pre>";
   Array(   
        [0] => Array(
                    [user_id] => 33
                    [tmp_id] => 3
        )
        [1] => Array(
                     [user_id] => 33
                     [tmp_id] => 4
          )
        )
    

`
`

    $arr = array(
        array('user_id' => 33, 'tmp_id' => 3),
        array('user_id' => 33, 'tmp_id' => 4),
        array('user_id' => 33, 'tmp_id' => 3),
        array('user_id' => 33, 'tmp_id' => 4),
    );
    $arr1 = array_unique($arr,SORT_REGULAR);
    echo "<pre>";
    print_r($arr1);
    echo "</pre>";
   Array(   
        [0] => Array(
                    [user_id] => 33
                    [tmp_id] => 3
        )
        [1] => Array(
                     [user_id] => 33
                     [tmp_id] => 4
          )
        )
    

`
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文