【问题标题】:Highlight duplicate values in a multidimensional array突出显示多维数组中的重复值
【发布时间】:2010-11-27 15:58:53
【问题描述】:

我正在输出购买清单,我想自动突出显示重复订单的存在。

这是数组的样子。前两个订单是错误下的重复订单。您会注意到每个的 orderid 不同,而 email 和 userid 保持不变。因此,重复项需要在电子邮件和/或用户 ID 上匹配,而不是在 orderid 上。

array
  0 => 
    array
      'orderid' => string '2009091008261662'
      'email' => string 'john@example.com'
      'userid' => string '53'
array
  1 => 
    array
      'orderid' => string '2009091008261048'
      'email' => string 'john@example.com'
      'userid' => string '53'
array
  2 => 
    array
      'orderid' => string '2009091008262025'
      'email' => string 'fred@example.com'
      'userid' => string '103'
array
  3 => 
    array
      'orderid' => string '2009091008272082'
      'email' => string 'tom@example.com'
      'userid' => string '392'

如何在 PHP 中搜索给定数组中同一个人的重复订单?

我想像这样输出上面的内容:

(假装在表格中)

2009091008261662 - john@example.com - 53

2009091008261048 - john@example.com - 53

2009091008262025 - fred@example.com - 103

2009091008272082 - tom@example.com - 392

...所以基本上只需突出显示两个(或更多)重复项。

【问题讨论】:

    标签: php multidimensional-array duplicate-data


    【解决方案1】:

    根据userid 值假设唯一性

    <?php
    
    $orders = array(
      array(
        'orderid' => '2009091008261662',
        'email' => 'john@example.com',
        'userid' => '53'
      ),
      array(
        'orderid' => '2009091008261048',
        'email' => 'john@example.com',
        'userid' => '53'
      ),
      array(
        'orderid' => '2009091008262025',
        'email' => 'fred@example.com',
        'userid' => '103'
      ),
      array(
        'orderid' => '2009091008272082',
        'email' => 'tom@example.com',
        'userid' => '392'
      ),
      array(
        'orderid' => '2009091008265555',
        'email' => 'john@example.com',
        'userid' => '53'
      )
    );
    
    $foundIds = array();
    foreach ( $orders as $index => $order )
    {
      if ( isset( $foundIds[$order['userid']] ) )
      {
        $orders[$index]['is_dupe'] = true;
        $orders[$foundIds[$order['userid']]]['is_dupe'] = true;
      } else {
        $orders[$index]['is_dupe'] = false;
      }
      $foundIds[$order['userid']] = $index;
    }
    ?>
    
    <style type="text/css">
    tr.dupe td {
      font-weight: bold;
    }
    </style>
    
    <table>
      <tr><th>orderid</th><th>email</th><th>
      <?php foreach ( $orders as $order ) { ?>
      <tr class="<?php echo $order['is_dupe'] ? 'dupe' : '' ?>">
        <td><?php echo $order['orderid']; ?></td>
        <td><?php echo $order['email']; ?></td>
        <td><?php echo $order['userid']; ?></td>
      </tr>
      <?php } ?>
    </table>
    

    【讨论】:

      【解决方案2】:

      您最好的选择是从本质上将数组“反转”为关联的一个,将值映射到原始数组中的键:

      $emails = array();
      $userids = array();
      
      foreach($inputarray as $key => $item) {
          if( isset($emails[$item['email']]) || isset($userids[$item['userid']]) ) {
              // This item has a duplicate email or userid as something already looked at!
              // $emails[$item['email']] or $userids[$item['userid']] has the key corresponding to the original location where it was seen.
              // $key has the key corresponding to the duplicate we just found.
          } else {
              $emails[$item['email']] = $key;
              $userids[$item['userid']] = $key;
          }
      }
      

      【讨论】:

        【解决方案3】:

        您可以向表示数组的内部数组添加一个哈希。只需循环并比较哈希值。

        【讨论】:

          【解决方案4】:

          此代码有效...

          $array1[0]['orderid'] = '2009091008261662';
          $array1[0]['email'] = 'john@example.com';
          $array1[0]['userid'] = '53';
          $array1[1]['orderid'] = '2009091008261662';
          $array1[1]['email'] = 'john@example.com';
          $array1[1]['userid'] = '53';
          $array1[2]['orderid'] = '2009091008261662';
          $array1[2]['email'] = 'john2@example.com';
          $array1[2]['userid'] = '53';
          $array1[3]['orderid'] = '209091008261662';
          $array1[3]['email'] = 'joh3@example.com';
          $array1[3]['userid'] = '53';
          $array1[4]['orderid'] = '2001008261662';
          $array1[4]['email'] = 'john@example.com';
          $array1[4]['userid'] = '53';
          $array1[5]['orderid'] = '20013344008261662';
          $array1[5]['email'] = 'johnddd@example.com';
          $array1[5]['userid'] = '53';
          $array1[6]['orderid'] = '200133352008261662';
          $array1[6]['email'] = 'johsdfgsdn@example.com';
          $array1[6]['userid'] = '53';
          
          
          $unique_array = array(); // Filtered array with no dupes
          $email_array = array(); // Hash list
          $order_array = array(); // Hash list
          foreach($array1 as $i => $row) {
          
           if (array_key_exists($row['email'], $email_array)) {
            // This is a dupe based on email
            $array1[$i]['duplicate'] = 1;
            $array1[$email_array[$row['email']]]['duplicate'] = 1;
           }
          
           if (array_key_exists($row['orderid'], $order_array)) {
            // This is a dupe based on email
            $array1[$i]['duplicate'] = 1;
            $array1[$order_array[$row['orderid']]]['duplicate'] = 1;
           }
           $order_array[$row['orderid']] = $i;
           $email_array[$row['email']] = $i;
          }
          foreach($array1 as $i => $row) {
           if (!empty($row['duplicate'])) {
            echo "<b>" . $row['orderid'] . $row['email'] . "</b>\n";
            unset($row['duplicate']); // reset the array to original form
           } else {
            echo $row['orderid'] . $row['email'] . "\n";
           }
          }
          

          【讨论】:

            【解决方案5】:

            您需要两次传递订单数组。但它确实比某些人想象的要简单:

            $duplicateUserId = array();
            
            // Mark user ID's with more than one order
            foreach ( $orders as $order ) {
                $duplicateUserId[$order['userid']] = isset($duplicateUserId[$order['userid']]);
            }
            
            // Output each order
            foreach ( $orders as $order ) {
                echo formatOrder($order, $duplicateUserId[$order['userid']]);
            }
            
            // Format the output of each order
            function formatOrder($order, $isDuplicated) {
                // yadda yadda yadda
            }
            

            假设 $orders 看起来像

            $orders = array(
              array(
                'orderid' => '2009091008261662',
                'email' => 'john@example.com',
                'userid' => '53'
              ),
              array(
                'orderid' => '2009091008261048',
                'email' => 'john@example.com',
                'userid' => '53'
              ),
              array(
                'orderid' => '2009091008262025',
                'email' => 'fred@example.com',
                'userid' => '103'
              ),
              array(
                'orderid' => '2009091008272082',
                'email' => 'tom@example.com',
                'userid' => '392'
              ),
              array(
                'orderid' => '2009091008265555',
                'email' => 'john@example.com',
                'userid' => '53'
              )
            );
            

            另外,最好只匹配 userId,因为大概用户可以更改他们的电子邮件,而电子邮件对于单个用户来说是唯一的。

            【讨论】:

              【解决方案6】:

              简单回答:

              function hasDuplicate($arr,$email) {
                $count = 0;
                foreach ($arr as $row) {
                   if ($row['email'] == $email) {
                     $count++;
                   }
                }
                return ($count >1);
              }
              

              【讨论】:

              • -1 表示 O(n^2),而它可能只是 O(2n) -> O(n)。此外,只要 $count 不为 0,您就可以返回 true,而不是迭代整个数组。
              • 我说这很简单,没有效率。提防过早的优化。是的,只要 $count > 1,您就可以返回 true。但不是 0,因为总会有 1 个匹配项。
              猜你喜欢
              • 1970-01-01
              • 2014-05-02
              • 2016-06-19
              • 2022-01-12
              • 2016-09-07
              • 1970-01-01
              • 2013-07-16
              • 2019-02-15
              相关资源
              最近更新 更多