I'm outputting a list of purchases, and I want to automatically highlight the presence of duplicate orders.
Here's what the array looks like. The first two orders are duplicate orders place by mistake. You'll notice that the orderid for each is different, while the email and userid remain the same. So the duplication will need to match on email and / or userid, but not on 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'
How can I search for duplicate orders from the same person in a given array, in PHP?
I would like to output the above like so:
(pretend its in a table)
2009091008261662 - john#example.com - 53
2009091008261048 - john#example.com - 53
2009091008262025 - fred#example.com - 103
2009091008272082 - tom#example.com - 392
... so basically just highlight the two ( or more ) duplicates.
Assumes uniqueness based on userid value
<?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>
Your best bet would be essentially "invert" the array into an associative one mapping values to keys from the original array:
$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;
}
}
You could add a hash to the inner-array which represents the the array. Just loop through and compare the hashes.
This code works...
$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";
}
}
You'll need two passes of the orders array. But it's really more simple than some have made it out to be:
$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
}
Assuming that $orders looks like
$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'
)
);
Also, it might be best to only match on userId since, presumably, users can change their emails and emails are unique to a single user.
Simple answer:
function hasDuplicate($arr,$email) {
$count = 0;
foreach ($arr as $row) {
if ($row['email'] == $email) {
$count++;
}
}
return ($count >1);
}
Related
my array image just like this, if subarray "name" is empty or null i want delete array, how to do that ?
here my current script
$data = array();
$fixedData = array();
$countyName = array();
$numrow = 2;
echo "<pre>";
// insert to tb participant => 1
foreach($sheet as $key => $row){
$data[] = array(
'name' => $this->split_name($row['B']),
'phone' => $row['D'],
'mobile' => $row['E'],
'institution' => $row['F'],
'departement' => $row['G'],
'address' => $row['H'],
'country' => $row['I'],
);
$numrow++;
}
unset($data[0]); //delete first row
$data = array_values($data);
//loop search data
var_dump ($data);
die();
Assume that you have the following data set,
$array = [
[
'name' => 'not null', 'phone' => 12546
],[
'name' => '', 'phone' => 852147
],[
'name' => null, 'phone' => 96325874
],[
'name' => 'have value', 'phone' => 12546
],
];
You can filter the nulled or empty values like several ways :
1-
foreach ($array as $key => &$value) {
if (empty($value['name']) || is_null($value['name'])) {
$value = null;
}
}
$array = array_filter($array);
2-
$newData = [];
foreach ($array as $key => $value) {
if (!empty($value['name']) && !is_null($value['name'])) {
$newData[] = $value;
}
}
3- using array_walk
$newData = [];
array_walk($array, function ($value, $key) use (&$newData) {
if (!empty($value['name']) && !is_null($value['name'])) {
$newData[] = $value;
}
});
4- using array_filter
$newData = array_filter($array, function ($value) {
if (!empty($value['name']) && !is_null($value['name'])) {
return $value;
}
});
<?php
$data = array();
$fixedData = array();
$countyName = array();
$numrow = 2;
echo "<pre>";
// insert to tb participant => 1
foreach($sheet as $key => $row){
if($this->split_name($row['B'])!=='' && $this->split_name($row['B'])!==NULL){
$data[] = array(
'name' => $this->split_name($row['B']),
'phone' => $row['D'],
'mobile' => $row['E'],
'institution' => $row['F'],
'departement' => $row['G'],
'address' => $row['H'],
'country' => $row['I'],
);
$numrow++;
}
}
//loop search data
var_dump ($data);
die();
I simple put an if condition inside your loop so you can check if your value is null or empty and if it is then you don't fill your new array. Also moved your counter inside the if so you increment it only in a success array push
A more "elegant" way for your if condition is this as well:
if (!empty($this->split_name($row['B'])) && !is_null($this->split_name($row['B'])))
I am having the following array with test data:
'team' =>
array (
0 =>
array (
'firstName' => 'adfadsf',
'lastName' => 'asdfadsfa',
'twitter' => 'ddasfasdf',
),
1 =>
array (
'firstName' => 'adf',
'lastName' => 'asd',
'twitter' => 'www.twitter.com/dfs',
),
2 =>
array (
'firstName' => 'asd',
'lastName' => 'adf',
'twitter' => 'www.twitter.com/adf',
),
3 =>
array (
'firstName' => 'test',
'lastName' => 'test',
'twitter' => 'www.twitter.com/test',
),
),
I would like to access the attributes firstName and lastName.
I tried the following, where $request has as one attribute the team array:
foreach ($request as $key => $value) {
Log::info($key);
$team = new Team();
$team->firstname = $request->team[$key]['firstName'];
$team->lastname = $request->team[$key]['lastName'];
$team->twitter = $request->team[$key]['twitter'];
$team->revisions_id = $revision->id;
Log::info("team");
Log::info($team);
$team->save();
}
Any suggestions how to access the two attributes firstName and lastName?
I appreciate your replies!
As it is not completely clear what's in $request, but I suggest this:
foreach ($request as $key => $value) {
Log::info($key);
if ($key == 'team') {
foreach ($value as $ar_team) {
$team = new Team();
$team->firstname = $ar_team['firstName'];
$team->lastname = $ar_team['lastName'];
$team->twitter = $ar_team['twitter'];
$team->revisions_id = $revision->id;
Log::info("team");
Log::info($team);
$team->save();
}
}
}
Or simply (if other items in $request are not used in foreach):
foreach ($request['team'] as $ar_team) {
$team = new Team();
$team->firstname = $ar_team['firstName'];
$team->lastname = $ar_team['lastName'];
$team->twitter = $ar_team['twitter'];
$team->revisions_id = $revision->id;
Log::info("team");
Log::info($team);
$team->save();
}
looking to your data sample
you should iterate over $request['team'] and accessing to $value for obtain firstName and lastname....
foreach ($request['team'] as $key => $value) {
Log::info($key);
$team = new Team();
$team->firstname = $value['firstName'];
$team->lastname = $value['lastName'];
$team->twitter = $value['twitter'];
$team->revisions_id = $revision->id;
Log::info("team");
Log::info($team);
$team->save();
}
Is there a better/more efficient way to loop through this data?
I need to loop through the array data with the 'Name' first and the 'ListID' second but the external API request generates the array as per the code below (the other way round).
// Array Data
$csList = array(
array(
'ListID' => 'BGERFwQTrHoseE4sweebqwyAxuJ9YU',
'Name' => 'Monthly Newsletter Subscribers'
),
array(
'ListID' => 'kHdUQMbELgMyojuATz9Dsbxz3WViVo',
'Name' => 'Special Mailout'
)
);
// Generate Array Varaibles
foreach($csList as $array => $values) {
foreach($values as $k => $v) {
for($i = 1; $i < count($csList); $i++) {
$csListData[$k][] = $v;
}
}
}
// Loop Data
for($i = 0; $i < count($csList); $i++) {
echo $csListData['Name'][$i].'<br>';
echo $csListData['ListID'][$i].'<br>';
}
It's not at all clear why you're rearranging the data. Loop over the array and access whatever keys you want in whatever order you want.
$csList = array(
array(
'ListID' => 'BGERFwQTrHoseE4sweebqwyAxuJ9YU',
'Name' => 'Monthly Newsletter Subscribers'
),
array(
'ListID' => 'kHdUQMbELgMyojuATz9Dsbxz3WViVo',
'Name' => 'Special Mailout'
)
);
foreach ($csList as $item) {
echo $item['Name'].'<br>';
echo $item['ListID'].'<br>';
}
Your inner for loop is useless. You can use the $array key to get your array as wanted :
foreach($csList as $array => $values) {
foreach($values as $k => $v) {
$csListData[$k][$array] = $v;
}
}
// Loop Data
for($i = 0, $c = count($csList); $i <$c; $i++) {
echo '<br>';
echo $csListData['Name'][$i].'<br>';
echo $csListData['ListID'][$i].'<br>';
}
Also, moving the count() out of the check will avoid to count at every iteration of the loop.
// Array Data
$csList = array(
array(
'ListID' => 'BGERFwQTrHoseE4sweebqwyAxuJ9YU',
'Name' => 'Monthly Newsletter Subscribers'
),
array(
'ListID' => 'kHdUQMbELgMyojuATz9Dsbxz3WViVo',
'Name' => 'Special Mailout'
)
);
You can do as follow:
$newCsList = array();
$newCsList = array_map(function ($val){
return array_reverse($val,true);
},$csList);
The result is like:
**Array (
[0] => Array (
[Name] => Monthly Newsletter Subscribers
[ListID] => BGERFwQTrHoseE4sweebqwyAxuJ9YU
)
[1] => Array (
[Name] => Special Mailout
[ListID] => kHdUQMbELgMyojuATz9Dsbxz3WViVo
)
)**
But for taking each element you can do:
$newCsList = array();
$newCsList = array_map(function ($val){
$my_test_ary = array_reverse($val);
echo $my_test_ary['Name'].'<br/>'.$my_test_ary['ListId'];
},$csList);
I have a query that returns multiple rows. I can't seem to find a way to store the rows in the $params array. Is there a way to loop throw and store each row in the $params variable
$aResult = $db->exec_sql($sql);
$params = array(
// where $aResult[o]'' would be row 1 [1] row 2 etc. //
'store_id' => $aResult[]['iStoreID'],
'user_id' => $aResult[]['iUserID'],
'store_name' => $aResult[]['cStoreName'],
'store_url' => $aResult[]['cStoreURL'],
'rid' => $aResult[]['cRID'],
'affiliate_id' => $aResult[]['iAffiliateID'],
'team_id' => $aResult[]['iTeamID'],
'bizOP' => $aResult[]['cDefaultBizOpp'],
'showBizOPp' => $aResult[]['iShowBizOppDropdown'],
'boPosting' => $aResult[]['iEnableBOPosting'],
'brandinglevel' => $aResult[]['iBrandingLevel']
);
thank you for your help
As simple as that:
$params = array();
foreach($aResult as $row) {
$params[] = array(
'store_id' => $row['iStoreID'],
'user_id' => $row['iUserID'],
'store_name' => $row['cStoreName'],
'store_url' => $row['cStoreURL'],
'rid' => $row['cRID'],
'affiliate_id' => $row['iAffiliateID'],
'team_id' => $row['iTeamID'],
'bizOP' => $row['cDefaultBizOpp'],
'showBizOPp' => $row['iShowBizOppDropdown'],
'boPosting' => $row['iEnableBOPosting'],
'brandinglevel' => $row['iBrandingLevel']
);
}
Without knowing the exact structure of the result array i guess you need something like this:
<?php
$params = array();
$mapping = array(
'store_id' => 'iStoredID',
'user_id' => 'iUserID',
// and so on...
);
foreach ($aResult as $row) {
$tempRow = array();
foreach ($row as $key => $value) {
$paramKey = isset($mapping[$key]) ? $mapping[$key] : $key;
$tempRow[$paramKey] = $value;
}
$params[] = $tempRow;
}
I use it like this
$aResult = mysql_query($sql);
while($data = mysql_fetch_array($result)) {
'store_id' = $aResult['iStoreID'];
}
At least that is the idea
I have a multidimensional array in the following format:
$array = array (
0 =>
array (
'date' => '2013-03-25',
'name' => 'Bob',
'time' => '11'
),
1 =>
array (
'date' => '2013-03-25',
'name' => 'Brian',
'time' => '13'
),
2 =>
array (
'date' => '2013-03-26',
'name' => 'Jack',
'time' => '14'
),
3 =>
array (
'date' => '2013-03-26',
'name' => 'Bob',
'time' => '14'
)
);
I am trying to get the names and corresponding times for each date. I have got the names using the following method:
$array2 = array();
foreach($array as $item) {
$array2[$item['date']][] = $item['name'];
}
and then using:
foreach($array2[$date] as $name)
to run a query on the names returned. But I am not sure how to get the corresponding 'time' key for each 'name' key in the second foreach loop.
Why you don't want to store both name and time for each date key?
$array2 = array();
foreach ($array as $item) {
$array2[$item['date']] []= array($item['time'], $item['name']);
}
You can reach name and time with this code:
foreach ($array2 as $row) {
$name = $row[0];
$time = $row[1];
}
You can try
$list = array();
foreach ( $array as $k => $item ) {
$list[$item['date']][] = array(
$item['name'],
$item['time']
);
}
foreach ( $list as $date => $data ) {
echo $date, PHP_EOL;
foreach ( $data as $var ) {
list($name, $time) = $var;
echo $name, " ", $time, PHP_EOL;
}
echo PHP_EOL;
}
Output
2013-03-25
Bob 11
Brian 13
2013-03-26
Jack 14
Bob 14
try the following:
foreach($array as $item) {
$array2[$item['date'][] = array('name' => $item['name'], 'time' => $item['time']);
}
foreach($array2[$date] as $name) {
echo $name['name'] . ' => ' . $name['time'] . "\n";
}