Solved

Remove Duplicates from a foreach loop

Posted on 2014-04-25
11
1,356 Views
Last Modified: 2014-05-14
How do I remove duplicates from a foreach loop?  I want to remove duplicate first_name and Last_name for the loop:
foreach ($result as $row)  {
	$cid = $row->customer_id;
	$fn = $row->first_name;
        $ln = $row->last_name;
		if ($user_id == $cid) {
    			echo $fn.' '.$ln;
		}
}

Open in new window

0
Comment
Question by:rgranlund
  • 3
  • 2
  • 2
  • +2
11 Comments
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 40023661
Why not remove the duplicates in your query rather than in the PHP?
0
 
LVL 7

Author Comment

by:rgranlund
ID: 40023673
I want to remove duplicate First Name and Last Name:
$sql = "SELECT DISTINCT
    		p1.ID AS ID,
    		pm1.meta_value AS customer_id,
			oi1.order_item_id AS order_item_id,
			om1.meta_value AS first_name,
			om2.meta_value AS last_name,
			om3.meta_value AS mailing_address,
			om4.meta_value AS mailing_address_2
			FROM wp_posts p1
			JOIN wp_postmeta pm1 ON (pm1.post_id = p1.ID AND pm1.meta_key = '_customer_user')
			JOIN wp_woocommerce_order_items oi1 ON (oi1.order_id = p1.ID)
			JOIN wp_woocommerce_order_itemmeta om1 ON (om1.order_item_id = oi1.order_item_id AND om1.meta_key = 'Applicant Information - First Name')
			JOIN wp_woocommerce_order_itemmeta om2 ON (om2.order_item_id = oi1.order_item_id AND om2.meta_key = 'Applicant Information - Last Name')
			JOIN wp_woocommerce_order_itemmeta om3 ON (om3.order_item_id = oi1.order_item_id AND om3.meta_key = 'Applicant Information - Mailing Address')
			JOIN wp_woocommerce_order_itemmeta om4 ON (om4.order_item_id = oi1.order_item_id AND om4.meta_key = 'Applicant Information - Mailing Address 2')
			
			WHERE p1.post_type = 'shop_order'";

Open in new window

0
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 40023724
"Remove" is a squishy term.  Do you want to remove them from the data base entirely?  Or do you want to remove duplicates from the results set of a single query?  PHP has some tools for this, and so does SQL.  But what if the first and last name are duplicates and the other information is different.  How would you know which of the records you wanted to keep?

If you have the information in PHP arrays you might use array_unique().
0
 
LVL 51

Expert Comment

by:Julian Hansen
ID: 40023780
The question is - why are you getting duplicate first name / last name?

If you have the distinct then the returned rows should be unique - if you are getting dupes in the first name / last name fields you have to look at why.

Can you post the first few rows of your query.
0
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 40023795
If you have the distinct then the returned rows should be unique...
Exactly:  The rows will be distinct, but that doesn't imply that the first and last name are. The question is what should be done if there are duplicates in the remaining column values? A Group By will probably be the resolution, but if there are duplicates in the remaining columns, then there can still be duplicates in the name fields.
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 48

Expert Comment

by:PortletPaul
ID: 40023891
Do you understand that "select distinct" works across the entire row?
(all columns are evaluated)

You are asking for rows by order item (one order may have many items) so it is not surprising that a client who has ordered several items will be repeated.

Try removing this line from your query
                  oi1.order_item_id AS order_item_id,


see "Select Distinct is returning duplicates ..."
0
 
LVL 51

Expert Comment

by:Julian Hansen
ID: 40024151
The rows will be distinct, but that doesn't imply that the first and last name are.
Precisely - which is why I recommended he post some rows so we can see what the data looks like. The comment was meant to say that the rows are unique - so if name / lastname are repeated there is something else in the row causing that and to solve it we need to see the data.

Without having access to the underlying table structure / data - we can't see what the fields in the joined tables that are in the result set creating the uniqueness on the row.

A group by will solve the problem - but on what - we need to see the resulting data.
0
 
LVL 7

Author Comment

by:rgranlund
ID: 40027627
Here is what I want to happen;
The query selects a First Name and Last Name AS name then and Item ID number.
John doe has made Two purchases and Jane Doe has made Three purchases. The name and the Item ID are mandatory.  So when I run the query I get:
Jane Doe Item_111
Jane Doe Item_222
Jane Doe Item_333
John Doe Item_111
John Doe Item_222

However, I don't want to repeat the name.  I want the return to look like this:
Jane Doe Item_111
               Item_222
               Item_333
John Doe Item_111
               Item_222

Then later on, if the output must contain a billing address, then It would look like:
Jane Doe 123 test Lane Item_111
                                      Item_222
                                      Item_333
John Doe 123 Testville Drive Item_111
                                              Item_222
0
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 40027671
OK, now that I can see that, I understand it to be a common design question.  You might be able to force something to happen with a really extreme SQL query, but most of us would probably just use the "view" portion of the script to accomplish the goal.  Here's a code sample from a recent similar question.  Please read it over and if you still have any questions, post back and I'll try to help. ~Ray
http://iconoun.com/demo/temp_sim1980.php

<?php // demo/temp_sim1980.php
error_reporting(E_ALL);
echo '<pre>' . PHP_EOL;

/**
 * SEE http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/HTML/Q_28418802.html
 *
 * Currently: SALLY  5  76" 4"
 *            SALLY  3  54" 5"
 *            SALLY  6  36" 4"
 *
 * Desirable: SALLY  5  76" 4"
 *                   3  54" 5"
 *                   6  36" 4"
 */

// SIMULATED TEST DATA
$rows = array
( array( 'nom' => 'BALLY', 'num' => 'A')
, array( 'nom' => 'SALLY', 'num' => '5')
, array( 'nom' => 'SALLY', 'num' => '3')
, array( 'nom' => 'SALLY', 'num' => '6')
, array( 'nom' => 'WILLY', 'num' => 'Z')
)
;

// CREATE AN HTML TABLE DOCUMENT
$out = '<table>' . PHP_EOL;

// STORE AN IMPOSSIBLE VALUE FOR THE PREVIOUS 'nom'
$old = FALSE;

// ITERATE OVER THE ROWS OF THE RESULTS SET
foreach ($rows as $row)
{
    $out .= '<tr>';

    // WHEN TO SHOW A NEW NAME IN THE ROW
    if ($row['nom'] != $old)
    {
        $old = $row['nom'];
        $out .= '<td>' . $row['nom'] . '</td>';
    }
    else
    {
        $out .= '<td>' . NULL        . '</td>';
    }

    // ADD IN THE REST OF THE ROW DATA HERE
    $out .= '<td>' . $row['num'] . '</td>';

    // CLOSE OFF THE ROW
    $out .= '</tr>' . PHP_EOL;
}

// CLOSE OFF THE TABLE AND SHOW THE WORK PRODUCT
$out .= '</table>' . PHP_EOL;
echo $out;

Open in new window

0
 
LVL 48

Accepted Solution

by:
PortletPaul earned 500 total points
ID: 40028519
for SQL these rows are "distinct" (every row is different)

Jane Doe Item_111
Jane Doe Item_222
Jane Doe Item_333
John Doe Item_111
John Doe Item_222

and a SQL query will repeat information that is common across those rows.

As Ray has discussed above, removing what I would call "unwanted repetition" from a query result is best done after your SQL query. You could concatenate the names in SQL but here even that might be more sensible in PHP.

Note, once you remove the unwanted repetition you won't be able to re-order the data easily, so sort it into the desired order within the query.
0
 
LVL 51

Expert Comment

by:Julian Hansen
ID: 40028920
Here is some code that can do what you want - BUT you need to understand your data.

If you have a situation where you have two different people with the same firstname / lastname combination you are going to end up with an ambiguous situation and very likely incorrect results. You would need to add something else to your row to determine uniqueness of firstname / lastname.
<?php
// ARRAY OF VALUES SIMULATING RETURN FROM THE DATABASE
$result = array (
  array('first_name' => 'Jane', 'last_name' => 'Doe', 'item' => 'Item_111'),
  array('first_name' => 'Jane', 'last_name' => 'Doe', 'item' => 'Item_222'),
  array('first_name' => 'Jane', 'last_name' => 'Doe', 'item' => 'Item_333'),
  array('first_name' => 'John', 'last_name' => 'Doe', 'item' => 'Item_111'),
  array('first_name' => 'John', 'last_name' => 'Doe', 'item' => 'Item_222')
);
?>
<h1>Example of output in a table</h1>
<table>
<?php
// A VARIABLE TO STORE THE NAME WE ARE BUSY WITH
$current = '';

// A FLAG TO DETERMINE IF WE SHOULD DISPLAY
// THE NAME OR IGNORE IT
$showname = true;

// LOOP THROUGH THE RESULTING ROWS
foreach ($result as $row)  {
  echo '<tr>';
  
  // IF THE CURRENT ROW IS NOT THE SAME FIRSTNAME / LASTNAME
  // AS THE PREVIOUS ROW THEN WE NEED TO SET THE FLAG
  // TO OUTPUT THE NEW NAME
  if ($current != $row['first_name'] . ' ' . $row['last_name']) {
  
    // SET THE showname FLAG TO TRUE TO TELL
    // THE OUTPUT CODE TO DUMP THE NAME
    $showname = true;
    
    // UPDATE THE current VARIABLE TO STORE THE 
    // NEW FIRSTNAME / LASTNAME
    $current = $row['first_name'] . ' ' . $row['last_name'];
  }
  echo '<td>';
  // IF showname IS TRUE THEN WE OUTPUT THE FIRSTNAME / LASTNAME
  if ($showname) {
    echo $row['first_name'] . ' ' . $row['last_name'];
    
    // AND SET showname TO FALSE TO IGNORE DUPLICATE NAMES
    // ON NEXT ITERATION
    $showname = false;
  }
  
  // REST OF DATA FOR ROW. EXPAND AS NECESSARY TO OUTPUT
  // ADDITIONAL FIELDS
  echo '</td><td>' . $row['item'] . '</td></tr>';
}
?>
</table>

Open in new window

0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Foreword (July, 2015) Since I first wrote this article, years ago, a great many more people have begun using the internet.  They are coming online from every part of the globe, learning, reading, shopping and spending money at an ever-increasing ra…
If you have heard of RFC822 date formats, they can be quite a challenge in SQL Server. RFC822 is an Internet standard format for email message headers, including all dates within those headers. The RFC822 protocols are available in detail at:   ht…
The viewer will learn how to count occurrences of each item in an array.
The viewer will learn how to create a basic form using some HTML5 and PHP for later processing. Set up your basic HTML file. Open your form tag and set the method and action attributes.: (CODE) Set up your first few inputs one for the name and …

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now