Remove duplicates array - php

I have an array looks like this,
Array
(
[0] => Array
(
[id] => 224983
[name] => James
[weight] => 0
[bank] => Bank A
[transaction] => 1
[total] => 7682000000
[reference] => Edward
[type] => BRANCH
[reference_id] => 222818
[account_number] => 1220007355285
)
[1] => Array
(
[id] => 224984
[name] => James
[weight] => 0
[bank] => Bank A
[transaction] => 1
[total] => 7682000000
[reference] => Edward
[type] => BRANCH
[reference_id] => 222819
[account_number] => 1220007355285
)
[3] => Array
(
[id] => 224985
[name] => Maria
[weight] => 0
[bank] => Bank B
[transaction] => 1
[total] => 1500000000
[reference] => Andrey
[type] => BRANCH
[reference_id] => 247620
[account_number] => 1220000412901
)
)
When the account_number, reference, and name is same I want to remove the other one, and keep the last based on id...
Please someone help me to find out, I've been stuck here, so the output would be remove array[0] with ['id] => 224983, and the rest array would be the result

If you specifically just want to compare only three field of array than you can try below way. Which checks of duplicate and unset previous entries. Here $data is array input
foreach ($data as $key => $row) {
$id = $row['id'];
$name = $row['name'];
$reference = $row['reference'];
$flag = 0;
for($i = $key + 1; $i < count($data); $i++)
{
if(($data[$i]['id'] == $id) && ($data[$i]['name'] == $name) && ($data[$i]['reference'] == $reference))
{
if($key != $i)
unset($data[$key]);
}
}
}
Result would be
Array
(
[1] => Array
(
[id] => 224983
[name] => James
[weight] => 0
[bank] => Bank A
[transaction] => 1
[total] => 7682000000
[reference] => Edward
[type] => BRANCH
[reference_id] => 222818
[account_number] => 1220007355285
)
[2] => Array
(
[id] => 224985
[name] => Maria
[weight] => 0
[bank] => Bank B
[transaction] => 1
[total] => 1500000000
[reference] => Andrey
[type] => BRANCH
[reference_id] => 247620
[account_number] => 1220000412901
)
)

Try the following function, This will help to remove duplicates arrays.
function array_unique_multidimensional($input)
{
$serialized = array_map('serialize', $input);
$unique = array_unique($serialized);
return array_intersect_key($input, $unique);
}

It seems inelegant, but I think you would need to loop through your previous array elements to check IDs. You could create a function something like this:
function id_exists_prior(&$my_array, $array_index) {
for($i = 0; $i < $array_index; $i++) {
if($my_array[$i]['id'] === $my_array[$array_index]['id']) return false;
}
return true;
}
Then you can call it on any array element you wish, or loop through the whole array to check for duplicates. An example of the latter:
$your_array = [/*Your array data*/];
for($key = 0; $key < count($your_array); $key++) {
if(id_exists_prior($your_array, $key)) //Do your thing
}
The reason for passing the array key into the function is so that the function ONLY checks for prior duplicates.
Hope this helps!

Related

How To Merge/push array into one in php

code
$result = [];
foreach ($getAllAgent as $rkey => $rvalue) {
$found = -1;
for ($i = 0; $i < count($result); $i++) {
if ($result[$i]["brokerid"] == $rvalue["brokerid"]) {
$found = $i;
$result[$i]['get_agent_details'][] = $rvalue['get_agent_details']; //here to combine
break;
}
}
// if not found, create new
if ($found == -1) {
$result[] = $rvalue;
}
results
Array
(
[0] => Array
(
[id] => 2
[brokerid] => 2
[agentid] => 3
[addedby] => 1
[get_agent_details] => Array
(
[id] => 3
[name] => kenang
[ic] => 932132923
[phone] => 2313123
[0] => Array
(
[id] => 4
[name] => ivan
[ic] => 32992131
[phone] => 31231
)
)
)
)
I have one set of an array, and I loop it and restructure match the data based on ID. After that I will try to merge the same data into one array, I able add into one array. But it will not combine as one. The correct result should be as below.
[get_agent_details] => Array
(
[0] => Array(
[id] => 3
[name] => kenang
[ic] => 932132923
[phone] => 2313123
),
[1] => Array
(
[id] => 4
[name] => ivan
[ic] => 32992131
[phone] => 31231
)
)
Your problem is in this line:
$result[] = $rvalue;
Consider the case where you only have one item; this will result in:
Array
(
[0] => Array
(
[id] => 2
[brokerid] => 2
[agentid] => 3
[addedby] => 1
[get_agent_details] => Array
(
[id] => 1
[name] => Chesney Hawkes
[ic] => 932132923
[phone] => 2313123
)
)
)
But to be consistent, you need get_agent_details to be a list of items, that happens to have one entry:
Array
(
[0] => Array
(
[id] => 2
[brokerid] => 2
[agentid] => 3
[addedby] => 1
[get_agent_details] => Array
(
[0] => Array
(
[id] => 1
[name] => Chesney Hawkes
[ic] => 932132923
[phone] => 2313123
)
)
)
)
So you need to re-arrange your data, for instance by writing:
$rvalue['get_agent_details'] = [0 => $rvalue['get_agent_details']];
$result[] = $rvalue;
Then, since get_agent_details will already be a list when you encounter a second matching item, your existing code in the inner loop will do the right thing:
// Add an item to the list
$result[$i]['get_agent_details'][] = $rvalue['get_agent_details'];

PHP Array re-arrange to Multi Dimensional

I have an array structure like this and wanted to Re-arrange it to the one below. Any suggestions for a faster/simple fix? I already did the addition of the dates. Thanks! :)
Input:
Array
(
[0] => Array
(
[user_id] => 255
[display_name] => Mark
[company_name] => Company_A
)
[1] => Array
(
[user_id] => 150
[display_name] => Paul
[company_name] => Company_A
)
[2] => Array
(
[user_id] => 25
[display_name] => Hulk
[company_name] => Company_B
)
[3] => Array
(
[user_id] => 50
[display_name] => Bob
[company_name] => Company_B
)
)
Output:
Array
(
[Company_A] => Array
(
[company_total_hours] => 20h 45m
[employees] => Array
(
[0] => Array
(
[user_id] => 255
[display_name] => Mark
)
[1] => Array
(
[user_id] => 150
[display_name] => Paul
)
)
)
[Company_B] => Array
(
[company_total_hours] => 7h 30m
[employees] => Array
(
[0] => Array
(
[user_id] => 25
[display_name] => Hulk
)
[1] => Array
(
[user_id] => 50
[display_name] => Bob
)
)
)
)
My Attempts:
<?php
$company_names = array();
foreach ($records as $k => $v) {
$company_names[] = $v->company_name;
}
$company_names = array_unique($company_names);
// hard coded testing
if (count($company_names) > 0) {
foreach($company_names as $k2 => $v2) {
$final_array[$v2]['company_total_hours'] = rand(1, 20);
$final_array[$v2]['employees'] = array(
array('user_id' => '255', 'display_name' => 'Mark'),
array('user_id' => '150', 'display_name' => 'Paul')
);
}
}
// on-going testing right now here....
I don't see where you derive your hours from so I left that out.
$i = 0;
foreach($vals as $keys => $arrays) {
if(!isset($new[$arrays['company_name']]))
$i = 0;
$new[$arrays['company_name']]['employees'][$i]['display_name'] = $arrays['display_name'];
$new[$arrays['company_name']]['employees'][$i]['user_id'] = $arrays['user_id'];
$i++;
}
Gives you:
Array
(
[Company_A] => Array
(
[employees] => Array
(
[0] => Array
(
[display_name] => Mark
[user_id] => 255
)
[1] => Array
(
[display_name] => Paul
[user_id] => 150
)
)
)
[Company_B] => Array
(
[employees] => Array
(
[0] => Array
(
[display_name] => Hulk
[user_id] => 25
)
[1] => Array
(
[display_name] => Bob
[user_id] => 50
)
)
)
)
foreach($arr as $v)
{
if(!$arr2[$v['company_name']]['employees'])
$arr2[$v['company_name']]['employees'] = array();
if(!$arr2[$v['company_name']]['company_total_hours'])
$arr2[$v['company_name']]['company_total_hours'] = '2h';//addional value
$arr2[$v['company_name']]['employees'][] = array('user_id'=>$v['user_id'],
'display_name'=>$v['display_name']
);
}
I have created a function which does the same thing as the answer given by #Rasclatt.
function groupByKeyValue($array, $oldKeyName, $newKeyName){
$newArray = array();
foreach($array as $key=>$value){
if(isset($newArray[$value[$oldKeyName]][$newKeyName])){
$newArray[$value[$oldKeyName]][$newKeyName][] = array('user_id'=> $value['user_id'], 'display_name' => $value['display_name']);
}else{
$newArray[$value[$oldKeyName]] = array($newKeyName => array(array('user_id'=> $value['user_id'], 'display_name' => $value['display_name'])));
}
}
return $newArray;
}
//usage
$newArray = groupByKeyValue($array, 'company_name', 'employees');
You can add a third parameter to send the keys for the array values which needs to be used in the new array for 'employees'. Please check this link for the working of the function http://goo.gl/I6Of5y

cannot find value in array

I can't see where I am wrong with this code so I kindly ask for your help.
I have two arrays:
Array (
[0] => Array (
[description] => Generali di Proprieta'
[idmov] => 34
[mov] => Manutenzioni
[total] => 8000
)
[1] => Array (
[description] => Generali di Proprieta'
[idmov] => 35
[mov] => Assicurazioni
[total] => 6000
)
[2] => Array (
[description] => Generali di Proprieta'
[idmov] => 36
[mov] => Cancelleria Postali
[total] => 1850
)
[3] => Array (
[description] => Generali di Proprieta'
[idmov] => 37
[mov] => Bancarie passive
[total] => 700
)
[4] => Array (
[description] => Generali di Proprieta'
[idmov] => 38
[mov] => Amministrazione
[total] => 15000
)
)
and
Array (
[0] => Array (
[center] => 8
[caus] => 34
[total] => 38175.04
)
[1] => Array (
[center] => 8
[caus] => 35
[total] => 6132.00
)
[2] => Array (
[center] => 8
[caus] => 36
[total] => 223.80
)
[3] => Array (
[center] => 8
[caus] => 37
[total] => 114.70
)
[4] => Array (
[center] => 8
[caus] => 38
[total] => 14625.07
)
[5] => Array (
[center] => 8
[caus] => 39
[total] => 7450.48
)
I use this function
function searchForId($id, $array) {
foreach ($array as $key => $val) {
if ($val['caus'] === $id) {
return $key;
}
}
return null;
}
to look in array B for each item of array A with this code:
for($i=0;$i<$length;$i++){
if(searchForId($voce_bdg[$i]['idmov'], $voce_actual)){
$key=searchForId($voce_bdg[$i]['idmov'], $voce_actual);
$actual=$voce_actual[$key]['importo'];
echo '<td class="report">'.number_format($actual,2,',','.').'</td>';
}else{
echo '<td class="report">0,00</td>';
}
}
It works for every item like a charm except for the first item where it returns 0.
Where am I wrong??
Thanks in advance for your help!
Lelio
PHP treats the index 0 as a false. As such, if you find your result in index zero, it won't pass the if() statement you have.
Since your function returns null if no record found, why not try to check for null?
for($i = 0; $i < $length; $i++)
{
// Use is_null() check below. If it is not null, it is found.
// Also, instead of doing searchForId() twice, just do it once and check for the result.
$key = searchForId($voce_bdg[$i]['idmov'], $voce_actual);
if(! is_null ($key))
{
$actual = $voce_actual[$key]['importo'];
echo '<td class="report">'.number_format($actual,2,',','.').'</td>';
}
else
{
echo '<td class="report">0,00</td>';
}
}
try replacing operator === for ==
It does return something. It return 0 since the key is 0. But your if() interpret it as a "false"
change
if(searchForId($voce_bdg[$i]['idmov'], $voce_actual)){
with
if(searchForId($voce_bdg[$i]['idmov'], $voce_actual) != null){

reorder multi-dimensional array in PHP

I have a multi-dimensional array that I need to reorder.
I need to sort the array so that the first thing that will take into account the LEVEL, then SECTION, where SECTION is equal to the ID of the previous element.
Can someone help me?
Thanks.
Here is the array:
Array
(
[0] => Array
(
[LEVEL] => 1
[ID] => 1_1
[SECTION] => _
)
[1] => Array
(
[LEVEL] => 1
[ID] => 1_2
[SECTION] => _
)
[2] => Array
(
[LEVEL] => 2
[ID] => 2_1
[SECTION] => 1_1
)
[3] => Array
(
[LEVEL] => 2
[ID] => 2_2
[SECTION] => 1_2
)
[4] => Array
(
[LEVEL] => 3
[ID] => 3_1
[SECTION] => 2_1
)
[5] => Array
(
[LEVEL] => 3
[ID] => 3_2
[SECTION] => 2_2
)
and here is the result I need:
Array
(
[0] => Array
(
[LEVEL] => 1
[ID] => 1_1
[SECTION] => _
)
[2] => Array
(
[LEVEL] => 2
[ID] => 2_1
[SECTION] => 1_1
)
[4] => Array
(
[LEVEL] => 3
[ID] => 3_1
[SECTION] => 2_1
)
[1] => Array
(
[LEVEL] => 1
[ID] => 1_2
[SECTION] => _
)
[3] => Array
(
[LEVEL] => 2
[ID] => 2_2
[SECTION] => 1_2
)
[5] => Array
(
[LEVEL] => 3
[ID] => 3_2
[SECTION] => 2_2
)
Correct me if I'm wrong, but it looks like all the information you need for sorting is in the ID. Groups are contained in the number following the underscore, and levels in the number preceding it. Therefore, the order can be determined by reversing the order of these numbers and performing a natural order string comparison:
1_1, 2_1, 3_1, 4_1, 1_2, 2_2, 3_2, 1_3, 2_3, 3_3, 4_3, etc.
Becomes:
1-1, 1-2, 1-3, 1-4, 2-1, 2-2, 2-3, 3-1, 3-2, 3-3, 3-4, etc.
Therefore, if your initial array is called $arr:
$ord = array_map(function($a) {return $a['ID'];}, $arr);
$ord = preg_replace('/(\d+)_(\d+)/', '$2-$1', $ord);
array_multisort($ord, SORT_NATURAL, $arr);
If you're using PHP 5.5:
$ord = preg_replace('/(\d+)_(\d+)/', '$2-$1', array_column($arr, 'ID'));
array_multisort($ord, SORT_NATURAL, $arr);
It was interesting to work on your question, Please check my below solution on your query,
It's working fine for me:
$arrData=array(
array(
'LEVEL'=>1,
'ID'=>'1_1',
'SECTION'=>''
),
array(
'LEVEL'=>'3',
'ID'=>'3_1',
'SECTION'=>''
),
array(
'LEVEL'=>'3',
'ID'=>'3_2',
'SECTION'=>''
),
array(
'LEVEL'=>2,
'ID'=>'2_1',
'SECTION'=>''
),
array(
'LEVEL'=>1,
'ID'=>'1_2',
'SECTION'=>''
),
);
$arrLevels=array();
foreach($arrData as $key=>$val)
{
if(!in_array($val['LEVEL'], $arrLevels))
{
$arrLevels[]=$val['LEVEL'];
}
}
sort($arrLevels);
$arrDataNew=array();
$arrSortIndexes=array();
do
{
foreach ($arrLevels as $level)
{
//array_walk($arrData, 'sort_data',$level,$arrSortIndexes,$arrData);
$arrCurrentLevel=array();
foreach($arrData as $key=>$dataC)
{
if($dataC['LEVEL']==$level)
{
$arrCurrentLevel[intval(end(explode('_',$dataC['ID'])))]=$key;
}
}
if(sizeof($arrCurrentLevel)>0)
{
$keyOfArrData=$arrCurrentLevel[min(array_keys($arrCurrentLevel))];
$arrDataNew[]=$arrData[$keyOfArrData];
unset($arrData[$keyOfArrData]);
}
}
}while(sizeof($arrData)>0);
print_r($arrDataNew);
I finally solved this way, it is not the fastest solution, but it works at least as need
$i=0;
foreach ($polozky as $id => $polozka)
{
if ($polozka["LEVEL"] == 1)
{
$i++;
}
}
$j=0;
foreach ($polozky as $id => $polozka)
{
if ($polozka["LEVEL"] == 2)
{
$j++;
}
}
$k=0;
foreach ($polozky as $id => $polozka)
{
if ($polozka["LEVEL"] == 3)
{
$k++;
}
}
$stack = array();
for($l = 0; $l < $i; ++$l)
{
array_push($stack, $polozky[$l]);
$id1 = $polozky[$l]["ID"];
for($m = 0; $m < $j+$i; ++$m)
{
if($polozky[$m]["SECTION"] == $id1)
{
array_push($stack, $polozky[$m]);
$id2 = $polozky[$m]["ID"];
for($n = 0; $n < $k+$j+$i; ++$n)
{
if($polozky[$n]["SECTION"] == $id2)
{
array_push($stack, $polozky[$n]);
}
}
}
}
}

PHP combine array based on value of particular element

I have an array that looks like this
Array (
[0] => Array
(
[id] => 123
[count] => 1
)
[1] => Array
(
[id] => 123
[count] => 3
)
[2] => Array
(
[id] => 513
[count] => 0
)
[3] => Array
(
[id] => 561
[count] => 1
)
[4] => Array
(
[id] => 613
[count] => 7
)
)
What I want to do is create a new array, that totals the count where the id values are the same. So for example, the new array would look like this:
Array (
[0] => Array
(
[id] => 123
[count] => 4
)
[1] => Array
(
[id] => 513
[count] => 0
)
[2] => Array
(
[id] => 561
[count] => 1
)
[3] => Array
(
[id] => 613
[count] => 7
)
)
Would anyone know a good method to do this?
Thank you!
Short and simple:
$new_array = array();
foreach($data_array as $value) {
if(array_key_exists($value['id'], $new_array)) {
$new_array[$value['id']] += $value['count'];
} else {
$new_array[$value['id']] = $value['count'];
}
}
echo print_r($new_array,true);
I made it id => value since there didn't seem to need another array for data when the id could be used as the array's key.
Any reason why you are not making an associative array of id => count
You can do it with the following function (I didn't tested the code, but it should work ):
function get_count_array($arr) {
$new_array = array();
foreach($arr as $item) {
$found = false;
//loop through all the current new items to check if we already have it
for($i = 0; $i < count($new_array); $i++) {
//do we have it?
if($new_array[$i]['id'] == $item['id']) {
$new_array[$i]['count'] += 1;
$found = true;
break;
}
}
if(!$found) {
$new_array[] = array('id' => $item['id'], 'count' => 0);
}
}
return $new_array;
}

Categories