remove duplicate values from multidimensional array by single value - php

Ok the thing is, Ive read and tried a lot of solutions found here based on complete duplicateness, BUT I need something a little bit different and cant figure it out...
Because I only want to get and remove the duplicate value if only 1 of the array values is duplicate.
And also later combine the two but that's not that difficult.
$a = array(
array(
'id' => 1,
'qty' => 1
),
array(
'id' => 0,
'qty' => 1
),
array(
'id' => 1,
'qty' => 2
)
);
What I want the outcome to be:
$b = array(
array(
'id' => 1,
'qty' => 3
),
array(
'id' => 0,
'qty' => 1
)
);

You can do something like the following:
<?php
$a = array(
array(
'id' => 1,
'qty' => 1
),
array(
'id' => 0,
'qty' => 1
),
array(
'id' => 1,
'qty' => 2
)
);
$idsList = array();
$res = array();
foreach ($a as $arr){
if (!in_array($arr['id'], $idsList)){
$res[$arr['id']] = $arr;
$idsList[] = $arr['id'];
}
else{
$res[$arr['id']]['qty'] += $arr['qty'];
}
}
echo "<pre>";
print_r($res);
To get array like that:
Array
(
[1] => Array
(
[id] => 1
[qty] => 3
)
[0] => Array
(
[id] => 0
[qty] => 1
)
)
Checkout This DEMO: http://codepad.org/UP0G7WnE

$a = array(
array(
'id' => 1,
'qty' => 1
),
array(
'id' => 0,
'qty' => 1
),
array(
'id' => 1,
'qty' => 2
)
);
$b = array();
$ids = array();
for($i = 0; $i < count($a); $i++)
{
if(in_array($a[$i]['id'], $ids))
{
$j = array_search($a[$i]['id'], array_values($ids));
$b[$j]['qty'] += $a[$i]['qty'];
}
else
{
$b[$i]['id'] = $a[$i]['id'];
$b[$i]['qty'] = $a[$i]['qty'];
$ids[] = $a[$i]['id'];
}
}
echo "<pre>";
print_r($b);

This could be a solution:
$temp = array();
foreach ($a as $data){
if (isset($temp[$data['id']])){
$temp[$data['id']] += $data['qty'];
} else {
$temp[$data['id']] = $data['qty'];
}
}
// Format array
$b = array();
foreach ($temp as $id => $qty){
$b[] = array(
'id' => $id,
'qty' => $qty
);
}
Output will be:
Array
(
[0] => Array
(
[id] => 1
[qty] => 3
)
[1] => Array
(
[id] => 0
[qty] => 1
)
)

Related

Sum array values by attribute name

I want to sum count values with same code.
This is my array:
$data = array(
array(
'code' => 02,
'count' => 8
),
array(
'code' => 03,
'count' => 1
),
array(
'code' => 03,
'count' => 1
),
array(
'code' => 03,
'count' => 7
),
array(
'code' => 11,
'count' => 1
),
array(
'code' => 11,
'count' => 5
),
array(
'code' => 17,
'count' => 4
),
array(
'code' => 17,
'count' => 2
),
array(
'code' => 17,
'count' => 8
)
);
Now I tried to group the array to sum the count with same code, but I think I'm wrong:
$new_data = [];
foreach($data as $k => $v){
$total = 0;
$new_data[$v['code']] = array(
'ttl' => $v['count'] + $total,
);
}
echo '<pre>';
print_r($new_data);
echo '</pre>';
What is the correct code for this? Thanks.
using isset will avoid undefined offset error:
$new_data = [];
foreach($data as $k => $v){
if (!isset($new_data[$v['code']]['ttl'])){
$new_data[$v['code']]['ttl'] = 0;
}
$new_data[$v['code']]['ttl'] += $v['count'];
}
print_r($new_data);
Assuming you want the keys in $new_data to to be the unique codes, and the values to be an an array with a key of ttl whose value is the sum of the counts for that particular code:
$new_data = [];
foreach($data as $v){
if (!array_key_exists($v['code'], $new_data)) {
$new_data[$v['code']]['ttl'] = $v['count'];
} else {
$new_data[$v['code']]['ttl'] += $v['count'];
}
}
I think this is what you want as output:
Array
(
[2] => Array
(
[ttl] => 8
)
[3] => Array
(
[ttl] => 9
)
[11] => Array
(
[ttl] => 6
)
[17] => Array
(
[ttl] => 14
)
)
If so, you can do minor modifications to your code such as this:
$new_data = [];
foreach ($data as $d) {
if (isset($new_data[$d['code']]['ttl'])) {
$new_data[$d['code']]['ttl'] += $d['count'];
} else {
$new_data[$d['code']]['ttl'] = $d['count'];
}
}

PHP : Concatenate arrays with condition

I'm trying to read a session variable, create arrays and concatenate them :
Session variable sample:
Array
(
[0] => Array
(
[idArticle] => 224
[ntypeArticle] => 1
)
[1] => Array
(
[idArticle] => 556
[ntypeArticle] => 2
)
[2] => Array
(
[idArticle] => 312
[ntypeArticle] => 1
)
)
I need to read this arrays one by one and create arrays by "ntypeArticle".
If ntypeArticle=1, create array1
If ntypeArticle=2, create array2
My code :
$type1 = array();
$type2= array();
$typeAll = array();
foreach($_SESSION['cart'] as $item)
{
if ($item['ntypeArticle'] == 1) {
$type1= array ( "Type" => '1', );
} else {
$type2= array ( "Type" => '2', );
}
array_push($typeAll , $type1 , $type2);
}
But this creates empty arrays.
Wanted output :
Array
(
[0] => Array
(
[type] => 1
)
[1] => Array
(
[type] => 2
)
[2] => Array
(
[type] => 1
)
)
All you need is this simple thing:
$out = [];
foreach($_SESSION['cart'] as $k => $item)
{
$out[$k] = ['Type' => $item['ntypeArticle']];
}
Now if you output $out variable you get what you need.
Try This
$newOp1 = array()
$newOp2 = array()
foreach($_SESSION['cart'] as $item){
if($item["ntypeArticle"] == 1){
$newOp1[]['type'] = $item["ntypeArticle"]
}else{
$newOp2[]['type'] = $item["ntypeArticle"]
}
}
print_r($newOp1);
print_r($newOp2);
Basing on information you provided, all you want to do is to extract nTypeArticle as type element. That's all.
//array from your example
$inputArray = array(
array(
'idArticle' => 224,
'nTypeArticle' => 1
),
array(
'idArticle' => 556,
'nTypeArticle' => 2
),
array(
'idArticle' => 312,
'nTypeArticle' => 1
),
);
$outputArray = array_map(function($inputElement) {
return array('type' => $inputElement['nTypeArticle']);
}, $inputArray);
var_dump($outputArray);
//Output (the same as yours):
//array (size=3)
// 0 =>
// array (size=1)
// 'type' => int 1
// 1 =>
// array (size=1)
// 'type' => int 2
// 2 =>
// array (size=1)
// 'type' => int 1
$output = new array();
$input = array(
array(
"idArticle" => 224,
"nTypeArticle" => 1
),
array(
"idArticle" => 556,
"nTypeArticle" => 2
),
array(
"idArticle" => 312,
"nTypeArticle" => 1
)
);
foreach($input as $article) {
array_push($output, new array("type"=>$article["nTypeArticle"]));
}
print_r($output);
This gives you the thing you asked for.
(Code has been not tested)

Find similar subarrays in some arrays

Have some arrays:
$a = array(
0 => array('value' => 1000, 'name' => 'AA1'),
1 => array('value' => 2000, 'name' => 'AA2'),
2 => array('value' => 3000, 'name' => 'AA3'),
3 => array('value' => 4000, 'name' => 'AA4'),
);
$b = array(
0 => array('value' => 1000, 'name' => 'BB1'),
1 => array('value' => 3000, 'name' => 'BB2'),
2 => array('value' => 1700, 'name' => 'BB3'),
3 => array('value' => 1200, 'name' => 'BB4'),
);
$c = array(
0 => array('value' => 3000, 'name' => 'CC1'),
1 => array('value' => 4000, 'name' => 'CC2'),
2 => array('value' => 4300, 'name' => 'CC3'),
3 => array('value' => 5000, 'name' => 'CC4'),
);
How can create a new array with the same variants from arrays $a, $b and $c? And order it by 'value' field..
$d = array(
0 => array('value' => 3000, 'name' => 'AA3');
);
Real example: http://3v4l.org/MAWjd
// Test Data
$timeVariantSerialized = 'a:3:{s:7:"group_a";a:3:{i:0;a:3:{s:10:"id_variant";i:122;s:4:"name";s:13:"3 hour 30 min";s:4:"time";i:12600;}i:1;a:3:{s:10:"id_variant";i:173;s:4:"name";s:6:"3 hour";s:4:"time";i:10800;}i:2;a:3:{s:10:"id_variant";i:271;s:4:"name";s:6:"1 hour";s:4:"time";i:3600;}}s:7:"group_b";a:2:{i:0;a:3:{s:10:"id_variant";i:107;s:4:"name";s:13:"1 hour 30 min";s:4:"time";i:5400;}i:1;a:3:{s:10:"id_variant";i:321;s:4:"name";s:6:"3 hour";s:4:"time";i:10800;}}s:7:"group_c";a:4:{i:0;a:3:{s:10:"id_variant";i:28;s:4:"name";s:6:"1 hour";s:4:"time";i:3600;}i:1;a:3:{s:10:"id_variant";i:98;s:4:"name";s:6:"3 hour";s:4:"time";i:10800;}i:2;a:3:{s:10:"id_variant";i:157;s:4:"name";s:6:"2 hour";s:4:"time";i:7200;}i:3;a:3:{s:10:"id_variant";i:158;s:4:"name";s:13:"1 hour 30 min";s:4:"time";i:5400;}}}';
// Test Data Array
$time_variant = unserialize( $timeVariantSerialized );
$groupsCount = count( $time_variant );
foreach( $time_variant as $groupId => $groupArray )
{
foreach( $groupArray as $groupChildId => $groupChildArray )
{
$timeCountsArray[$groupChildArray['time']][$groupId] = $groupChildId;
}
}
$result = array();
foreach( $timeCountsArray as $time => $groupIdsArray )
{
if( $groupsCount > count( $groupIdsArray ) ) continue;
foreach( $groupIdsArray as $groupId => $groupChildId )
{
$result[$time_variant[$groupId][$groupChildId]['id_variant']]
= $time_variant[$groupId][$groupChildId];
// If you need only one result , uncomment the below break
// break;
}
// If more than 1 time could have variants , comment out below break to get them all
break;
}
ksort( $result );
print_r( $result );
Result Array :
array
(
'98' => array
(
'id_variant' => 98
'name' => 3 hour
'time' => 10800
)
'173' => array
(
'id_variant' => 173
'name' => 3 hour
'time' => 10800
)
'321' => array
(
'id_variant' => 321
'name' => 3 hour
'time' => 10800
)
)
I'm not sure if this is what you want.
The result is a single array with all the repeated values in the given arrays:
//Lets merge them into a big array to work in a easier way;
//It will be a single level array as follow: [a0] => 1000, [a1] => 2000 etc.
$array = array('a' => $a, 'b' => $b, 'c' =>$c);
foreach($array as $letter => $subArray){
foreach($subArray as $key => $values){
$newArray[$letter.$key] = $values['value'];
}
}
$uniques = array_unique($newArray); //getting the non-repeated values
$repeated = array_diff_assoc($newArray, $uniques); // stripping them out
$final = array_unique($repeated); //cleaning the repeated values to just 1 of each
print_r($final);
Result
Array
(
[b0] => 1000
[b1] => 3000
[c1] => 4000
)

Group array rows by one column and only create a subarray from another column if more than one value

How can I group row data from a two-dimensional array and only create a subarray of another column if the respective group contains more than one value?
In other words, I need to group rows by id and conditionally restructure an array of arrays to have a variable depth of either 2 or 3 levels.
Input:
[
['id' => 567, 'value' => 780],
['id' => 676, 'value' => 743],
['id' => 676, 'value' => 721],
['id' => 234, 'value' => 766],
['id' => 234, 'value' => 680]
]
Desired output:
[
['id' => 567, 'value' => 780],
['id' => 676, 'value' => [743, 721]],
['id' => 234, 'value' => [766, 680]]
]
Are you sure you want to have the value as an integer when there is one value and an array when there are more?
<?php
$array = array(
array('id' => 567, 'value' => 780),
array('id' => 676, 'value' => 743),
array('id' => 676, 'value' => 721),
array('id' => 234, 'value' => 766),
array('id' => 234, 'value' => 680)
);
foreach ($array as $item) {
$result[$item['id']][] = $item['value'];
}
foreach ($result as $id => $value) {
if (count($value) > 1) {
$output[] = array(
'id' => $id,
'value' => $value
);
} else {
$output[] = array(
'id' => $id,
'value' => $value[0]
);
}
}
echo '<pre>';
print_r($output);
echo '</pre>';
?>
If not
<?php
$array = array(
array('id' => 567, 'value' => 780),
array('id' => 676, 'value' => 743),
array('id' => 676, 'value' => 721),
array('id' => 234, 'value' => 766),
array('id' => 234, 'value' => 680)
);
foreach ($array as $item) {
$result[$item['id']][] = $item['value'];
}
foreach ($result as $id => $value) {
$output[] = array(
'id' => $id,
'value' => $value
);
}
echo '<pre>';
print_r($output);
echo '</pre>';
?>
try this one
$array['key1'] = array(
0=>array('id'=>567, 'value'=>780),
1=>array('id'=>676, 'value'=>743),
2=>array('id'=>676, 'value'=>721),
3=>array('id'=>234, 'value'=>766),
4=>array('id'=>234, 'value'=>780)
);
foreach($array['key1'] as $subarray){
$group_id = $subarray['id'];
if(!isset($return[$group_id]))
$return[$group_id] = $subarray;
else{
if(is_array($return[$group_id]['value']))
array_push($return[$group_id]['value'], $subarray['value']);
else
$return[$group_id]['value'] = array($subarray['value'], $return[$group_id]['value']);
}
}
// reset grouping keys into 0,1...
$return = array_values($return);
print_r($return);
There, all the work done for you. How easy is that!
//create the array as you have now
$array[0] = ['id'=>567, 'value'=>780];
$array[1] = ['id'=>676, 'value'=>743];
$array[2] = ['id'=>676, 'value'=>721];
$array[3] = ['id'=>234, 'value'=>766];
$array[4] = ['id'=>234, 'value'=>780];
print_r($array);
print chr(10).chr(10);
//create a new array with the values combined on key
$concat = array();
foreach($array as $val) {
$i = $val['id'];
$v = $val['value'];
if (!is_array($concat[$i]))
$concat[$i] = array();
$concat[$i][] = $v;
}
print_r($concat);
print chr(10).chr(10);
//create a new array to show the data as you want.
$newarray = array();
foreach($concat as $key=>$val) {
$t = array();
$t['id'] = $key;
if (count($val)==1)
$t['value'] = $val[0];
else {
$t['value'] = array();
foreach($val as $v)
$t['value'][] = $v;
}
$newarray[] = $t;
}
print_r($newarray);
print chr(10).chr(10);
Result:
Array
(
[0] => Array
(
[id] => 567
[value] => 780
)
[1] => Array
(
[id] => 676
[value] => 743
)
[2] => Array
(
[id] => 676
[value] => 721
)
[3] => Array
(
[id] => 234
[value] => 766
)
[4] => Array
(
[id] => 234
[value] => 780
)
)
Array
(
[567] => Array
(
[0] => 780
)
[676] => Array
(
[0] => 743
[1] => 721
)
[234] => Array
(
[0] => 766
[1] => 780
)
)
Array
(
[0] => Array
(
[id] => 567
[value] => 780
)
[1] => Array
(
[id] => 676
[value] => Array
(
[0] => 743
[1] => 721
)
)
[2] => Array
(
[id] => 234
[value] => Array
(
[0] => 766
[1] => 780
)
)
)
<?php
$arr['key1'] = array(
array(
'id' => 567,
'value' => 780,
),
array(
'id' => 676,
'value' => 743,
),
array(
'id' => 676,
'value' => 721,
),
array(
'id' => 234,
'value' => 766,
),
array(
'id' => 234,
'value' => 780,
),
);
/* handle element merge */
function array_internal_merge_func($a, $b) {
if ( is_array($a['value']) )
$a['value'][] = $b['value'];
else
$a['value'] = array($a['value'], $b['value']);
return $a;
}
/* handle array merge */
function array_internal_merge($array, $key, $merge_func) {
$hashed = array();
$result = array();
foreach ( $array as $idx => $ele )
$hashed[$ele[$key]][] = $idx;
foreach ( $hashed as $key => $idxies ) {
reset($idxies);
$idx0 = current($idxies);
$result[$idx0] = $array[$idx0];
while ( $idx = next($idxies) )
$result[$idx0] = $merge_func($result[$idx0], $array[$idx]);
}
return $result;
}
print_r(array_internal_merge($arr['key1'], 'id', 'array_internal_merge_func'));
This task can certainly be done concisely with one loop.
Use id column values as temporary first level keys. This makes identifying duplicates most efficient and easy.
While iterating:
if a row's id is new to the result array, then push the whole row (in its original, flat structure) into the result array; or
if a row's id was encountered before, then cast the stored row's value element as an array before pushing the current row's value into that subarray.
If you do not want your result to have id values as the first level keys, then call array_values() to re-index the result.
The special action done implemented below is that when casting a scalar or null data type to an array, the value becomes the lone element of the newly formed array. If an array is explicitly cast as an array, then there is no effect on the data structure at all. This is why (array) can be unconditionally applied in the else branch.
Code: (Demo)
foreach ($array as $row) {
if (!isset($result[$row['id']])) {
$result[$row['id']] = $row;
} else {
$result[$row['id']]['value'] = array_merge(
(array) $result[$row['id']]['value'],
[$row['value']]
);
}
}
var_export(array_values($result));
An alternative without array_merge(): (Demo)
foreach ($array as $row) {
if (!isset($result[$row['id']])) {
$result[$row['id']] = $row;
} else {
$result[$row['id']]['value'] = (array) $result[$row['id']]['value'];
$result[$row['id']]['value'][] = $row['value'];
}
}
var_export(array_values($result));
An alternative with array_reduce(): (Demo)
var_export(
array_values(
array_reduce(
$array,
function($result, $row) {
if (!isset($result[$row['id']])) {
$result[$row['id']] = $row;
} else {
$result[$row['id']]['value'] = (array) $result[$row['id']]['value'];
$result[$row['id']]['value'][] = $row['value'];
}
return $result;
}
)
)
);

Find duplicate array values and delete conditionally

I have an multidimensional array like this:
$orders = array(
array(
'id' => '123',
'name' => 'John',
'lastname'=>'Carter',
'rate' => '1.0'
),
array(
'id' => '546',
'name' => 'Ben',
'lastname'=>'Wall',
'rate' => '0.25'
),
array(
'id' => '666',
'name' => 'John Bow',
'lastname'=>'Porter',
'rate' => '0.25'
),
array(
'id' => '156',
'name' => 'John',
'lastname'=>'Carter',
'rate' => '0.5'
)
);
and want make a function that will be delete duplicate rows that rate < 1.0. The result array should be:
$orders = array(
array(
'id' => '123',
'name' => 'John',
'lastname'=>'Carter',
'rate' => '1.0'
),
array(
'id' => '546',
'name' => 'Ben',
'lastname'=>'Wall',
'rate' => '0.25'
),
array(
'id' => '666',
'name' => 'John',
'lastname'=>'Porter',
'rate' => '0.25'
)
);
Not very beautiful and speed, but workable solution:
$a = array(...); // Your array
$hashstack = array_map(function($value) { return md5($value['name'] . $value['lastname']); }, $a);
$result = array_filter($a, function($value) use ($hashstack)
{
if ((float)$value['rate'] < 1.0) {
$count = 0;
foreach ($hashstack as $hash) {
if (md5($value['name'] . $value['lastname']) == $hash) {
$count++;
}
}
if ($count > 1) {
unset($value);
return;
}
}
return $value;
});
Result is the same of yours.
Edit: Second and good version here: http://ideone.com/zJ8vj
What do You mean by 'duplicated' - same 'rate' ?
Bellow example remove duplicated orders with same 'rate' and 'rate' < 1.0.
Is this what You need ?
$tmpOrders = array();
foreach($orders as $order) {
// Check only rate < 1.0
if((float)$order['rate'] < 1.0) {
// Check duplicate
$exists = false;
foreach($tmpOrders as $tmp) {
if($tmp['rate'] == $order['rate']) {
$exists = true;
break;
}
}
// Add if rate not exists
if(!$exists) {
$tmpOrders[] = $order;
}
}
// Add all with rate >= 1.0
else {
$tmpOrders[] = $order;
}
}
$orders = $tmpOrders;
echo "<pre>";
print_r($orders);
echo "<pre>";
Result:
Array
(
[0] => Array
(
[id] => 123
[name] => John
[lastname] => Carter
[rate] => 1.0
)
[1] => Array
(
[id] => 546
[name] => Ben
[lastname] => Wall
[rate] => 0.25
)
[2] => Array
(
[id] => 156
[name] => John
[lastname] => Carter
[rate] => 0.5
)
)

Categories