Removing similar elements from a PHP array - php

I have an array structured like this:
$arrNames = array(
array('first'=>'John', 'last'=>'Smith', 'id'=>'1'),
array('first'=>'John', 'last'=>'Smith', 'id'=>'2'),
array('first'=>'John', 'last'=>'Smith', 'id'=>'3')
)
I need to remove the similar elements where the fist and last name are the same. Normally, I would use array_unique but the elements aren't exactly unique since each one has a unique id. I do not care which id is retained. I just need the array to look like this:
$arrNames = array(
array('first'=>'John', 'last'=>'Smith', 'id'=>'1') // can be any id from the original array
)
Is there a quick way to accomplish this? My first thought is to use something like a bubble sort but I'm wondering if there is a better (faster) way. The resulting array is being added to a drop-down list box and the duplicate entries is confusing some users. I'm using the ID to pull the record back from the DB after it is selected. Therefore, it must be included in the array.

<?php
$arrNames = array(
array('first'=>'John', 'last'=>'Smith', id=>'1'),
array('first'=>'John', 'last'=>'Smith', id=>'2'),
array('first'=>'John', 'last'=>'Smith', id=>'3')
);
$arrFound = array();
foreach ($arrNames as $intKey => $arrPerson) {
$arrPersonNoId = array(
'first' => $arrPerson['first'],
'last' => $arrPerson['last']
);
if (in_array($arrPersonNoId, $arrFound)) {
unset($arrNames[$intKey]);
} else {
$arrFound[] = $arrPersonNoId;
}
}
unset($arrFound, $intKey, $arrPerson, $arrPersonNoId);
print_r($arrNames);
This definitely works, whether it is the best way is up for debate...
Codepad

There is no fast and easy way that I know of, but here is a relatively simple way of doing it assuming that the ids for "similar elements" don't matter (i.e. you just need an ID period).
$final = array();
foreach ($array as $values) {
$final[$values['first'] . $values['last']] = $values;
}
$array = array_values($final);
The last step is not strictly necessary .. only if you want to remove the derived keys.

Related

Joining Two Arrays Together and Counting Unique Id by using Laravel, PHP

I have those two arrays that I added to attachments.
"PartnerAffiliateCodeId" from first array and "Id" from second array is our primary key.
"UserAction" must be counted for every unique "PartnerAffiliateCodeId" so in our case it is 5.
Normally I think this must be done by SQL but unfortunately this is a API method that I am receiving so I have to handle it by PHP.
Any ideas about how I can make such join with PHP using these two arrays?
I'm unclear on exactly what you're trying to get at with UserAction, but you could try something like this:
//$array1 = the first array
//$array2 = the second array
array_push($array_1, array(
"DateTime" => "",
"HttpReferer" => "",
"Id" => count($array1),
"PartnerAffiliateCodeId" => $array2["Id"],
"UserAction" => "Click"
));
It sounds like you want to match the ID key to the PartnerAffiliateCodeId in your returned data set.
Without knowing your setup, or bothinging with total optimization here a workable solution which will give you some direction.
function selectPartnerWhere($id=null; $from=array())
{
$codes = array();
foreach($from as $k => $p)
{
if($id == $p['PartnerAffiliateCodeId'])
{
return $from[$k];
}
}
return array();
}
$theData = //your array above
$thePartner = //your partner above
$partnerData = selectPartnerWhere($thePartner['Id'], $theData);

Need help to grouping php arrays to make it better

First of all, my grouping is working but I feel it is dirty. Need someone to make it looks
clean and better.
I have following foreach
$data['new_array'] = array(); //I have to use $data['new_array'] because I need to pass it to template.
foreach ($get_topics as $topic) {
//Is that possible to make these 4 lines shorter?
$data['new_array'][$topic['tid']]['tid'] = $topic['tid'];
$data['new_array'][$topic['tid']]['title'] = $topic['title'];
$data['new_array'][$topic['tid']]['yes'] = $topic['yes'];
$data['new_array'][$topic['tid']]['no'] = $topic['no'];
//The belows are subarray grouping, it actually works but I need better solutions
//$new_array[$topic['tid']]['vid'][$topic['vid']][] = $topic['vid'];
//$new_array[$topic['tid']]['vid'][$topic['vid']][] = $topic['yesno'];
}
I wouldn't even try to make it shorter, but here's your code in a good looking version.
$data['new_array'] = array();
foreach ($get_topics as $topic) {
$data['new_array'][$topic['tid']] = array(
'tid' => $topic['tid'],
'title' => $topic['title'],
'yes' => $topic['yes'],
'no' => $topic['no']
);
}
Not sure what type is $topic['tid'] but you should be careful when using non-consecutive numbers as array keys.

Array of strings to array of arrays

I have an array of strings in PHP like this:
people = array("John","Kim");
I want to convert each of those strings into arrays themselves. Basically, I now want a 2-dimensional array like
people(John[],Kim[]);
I've been struggling with the implementation and am not sure how to do it.
$people = array_fill_keys(array("John","Kim"), array());
Based on your comment, you should be using a combination of keys or values if you want to do this with multi dimensional arrays (which I'm not sure is the best way, but can't say w/o further context).
$people = array(
"john" => array()
);
Then when you want to add products, just go like:
$people["john"]["couch"] = 3; // bought 3 times.
$people["john"][$item] = 0; // if you don't know the count yet for whatever reason. You can always chagne it later the same way.
Now:
foreach( $people as $person => $purchases ){
echo UCFirst( $person );
if( ! empty( $purchases ) ){
echo ' has bought:<br />';
foreach( $purchases as $item => $qty ){
echo $item.' ('.$qty.')<br />';
}
}
}
I would recommend always making your keys either uppercase or lowercase if you are going to use named. Your call though.
If you give us more code / context, there may be much better ways to do this stuff.

Problem with associative arrays

I have always sucked at complex arrays there must be something in my brain preventing me from ever understanding them. I will try to make this example really simple so we will not go off topic. I use this code to use numbers to represent each file name:
$mod_nums = array('1' => $input_zip_path . '01_mod_1.0.2.zip',
'2' => $input_zip_path . '02_mod_1.0.1.zip',
);
So when I use $mod_nums['01'] it will display the path to that file. I have an array from the script that put these $mod_nums values into an array like so:
$files_to_zip = array(
$mod_nums['1'],
$mod_nums['2']
);
That worked fine. Now I wanted to add a $_POST value so that I can enter numbers like 1,2 and other numbers that I add to the $mod_nums array later like 1,3,6,12 for example. So I used an explode for those posted values:
$explode_mods = explode(",", trim($_POST['mods']));
Now for the big question that is racking my brain and spent hours on and cannot get it to work.... I need for $files_to_zip to still be in an array and display the posted values of $mod_nums. So it would be like:
$files_to_zip = array( HAVE $_POSTED VALUES IN HERE );
I hope that makes sense. I need $files_to_zip to remain in array format, grab the file path to the zip files from the $mod_nums array, and display it all correctly so it would dynamically output:
$files_to_zip = array('01_mod_1.0.2.zip', '02_mod_1.0.1.zip');
so posted numbers will appear in an array format for the $files_to_zip variable. Make sense? In short I need an array to have dynamic values. Thanks :)
EDIT
Phew I figured it out myself from memory when I worked on something similar many years ago. This looks tough but it isn't. I had to use a foreach and assign the variable into an array like so:
$blah = array();
foreach ($explode_mods as $value)
{
$blah[] = $mod_nums[$value];
}
then I just assigned $files_to_zip to $blah:
$files_to_zip = $blah;
works perfectly :) I just forgot how to dynamically assign values into an array.
// filenames array
$mod_nums = array('1' => $input_zip_path . '01_mod_1.0.2.zip',
'2' => $input_zip_path . '02_mod_1.0.1.zip',
);
// mod_num keys
$explode_mods = explode(',', trim($_POST['mods']));
// array to hold filenames
$files_to_zip = array();
// loop over all the mod_num keys submitted via POST
foreach($explode_mods as $key){
// save the filename to the corresponding array
$files_to_zip[] = $mod_nums[$key];
}
maybe i havn't understood you right, but won't this just be a simple foreach-loop to add the entrys to $files_to_zip like this:
$explode_mods = explode(",", trim($_POST['mods']));
foreach($explode_mods as $k){
$files_to_zip[] = $mod_nums[$k];
}

Change the array KEY to a value from sub array

This is the set of result from my database
print_r($plan);
Array
(
[0] => Array
(
[id] => 2
[subscr_unit] => D
[subscr_period] =>
[subscr_fee] =>
)
[1] => Array
(
[id] => 3
[subscr_unit] => M,Y
[subscr_period] => 1,1
[subscr_fee] => 90,1000
)
[2] => Array
(
[id] => 32
[subscr_unit] => M,Y
[subscr_period] => 1,1
[subscr_fee] => 150,1500
)
)
How can I change the $plan[0] to $plan[value_of_id]
Thank You.
This won't do it in-place, but:
$new_plan = array();
foreach ($plan as $item)
{
$new_plan[$item['id']] = $item;
}
This may be a bit late but I've been looking for a solution to the same problem. But since all of the other answers involve loops and are too complicated imho, I've been trying some stuff myself.
The outcome
$items = array_combine(array_column($items, 'id'), $items);
It's as simple as that.
You could also use array_reduce which is generally used for, well, reducing an array. That said it can be used to achieve an array format like you want by simple returning the same items as in the input array but with the required keys.
// Note: Uses anonymous function syntax only available as of PHP 5.3.0
// Could use create_function() or callback to a named function
$plan = array_reduce($plan, function($reduced, $current) {
$reduced[$current['id']] = $current;
return $reduced;
});
Note however, if the paragraph above did not make it clear, this approach is overkill for your individual requirements as outlined in the question. It might prove useful however to readers looking to do a little more with the array than simply changing the keys.
Seeing the code you used to assemble $plan would be helpful, but I'm going assume it was something like this
while ($line = $RES->fetch_assoc()) {
$plan[] = $line;
}
You can simply assign an explicit value while pulling the data from your database, like this:
while ($line = $RES->fetch_assoc()) {
$plan[$line['id']] = $line;
}
This is assuming $RES is the result set from your database query.
In my opinion, there is no simpler or more expressive technique than array_column() with a null second parameter. The null parameter informs the function to retain all elements in each subarray, the new 1st level keys are derived from the column nominated in the third parameter of array_column().
Code: (Demo)
$plan = array_column($plan, null, 'id');
Note: this technique is also commonly used to ensure that all subarrays contain a unique value within the parent array. This occurs because arrays may not contain duplicate keys on the same level. Consequently, if a duplicate value occurs while using array_column(), then previous subarrays will be overwritten by each subsequent occurrence of the same value to be used as the new key.
Demonstration of "data loss" due to new key collision.
$plans = array();
foreach($plan as $item)
{
$plans[$item['id']] = $item;
}
$plans contains the associative array.
This is just a simple solution.
$newplan = array();
foreach($plan as $value) {
$id = $value["id"];
unset($value["id"]);
$newplan[$id] = $value;
}

Categories