Remove consecutive array with duplicate values in multidimensional array using PHP - php

I working on a function which filters a multi dimensional array, if the successive arrays have same value, I need to remove the arrays in between and get only the first and last of the successive arrays with duplicate values.
I cant figure out how to do this.
Hope you can help me.
Thanks.
SAMPLE CODE
function removeDuplicates($array){
$result = [];
$count = 0;
$firstValue = null;
for ($i = 0; $i < count($array); $i++) {
if($array[$i]['id'] == firstValue){
$result[] = $array[$i]);
}else{
// do action
}
}
return $array;
}
Sample Array
Array (
[0] => Array (
[key] => 0
[value] => 25
)
[1] => Array (
[key] => 1
[value] => 25
)
[2] => Array (
[key] => 2
[value] => 25
)
[3] => Array (
[key] => 3
[value] => 33
)
[4] => Array (
[key] => 4
[value] => 45
)
[5] => Array (
[key] => 5
[value] => 66
)
[6] => Array (
[key] => 6
[value] => 66
)
[7] => Array (
[key] => 7
[value] => 66
)
[8] => Array (
[key] => 8
[value] => 66
)
[9] => Array (
[key] => 9
[value] => 55
)
)
Here the first 3 arrays have same values (25), I need to remove the 2nd array and retain the 1st and 3rd, also with the 6th to 9th only retain the 6th and 9th array.
Expected Result
Array (
[0] => Array (
[key] => 0
[value] => 25
)
[2] => Array (
[key] => 2
[value] => 25
)
[3] => Array (
[key] => 3
[value] => 33
)
[4] => Array (
[key] => 4
[value] => 45
)
[5] => Array (
[key] => 5
[value] => 66
)
[8] => Array (
[key] => 8
[value] => 66
)
[9] => Array (
[key] => 9
[value] => 55
)
)

Try this:
$array = [
["key" => 0, "value" => 25],
["key" => 1, "value" => 25],
["key" => 2, "value" => 25],
["key" => 3, "value" => 33],
["key" => 4, "value" => 45],
["key" => 5, "value" => 66],
["key" => 6, "value" => 66],
["key" => 7, "value" => 66],
["key" => 8, "value" => 66],
["key" => 9, "value" => 55],
];
for ($i = 0; $i < count($array); $i++) {
if (!isset($array[$i])){
continue;
}
if ($array[$i]['value'] == $array[$i+1]['value']) {
$j = 1;
while ($array[$i]['value'] == $array[$i+$j+1]['value']) {
unset($array[$i+$j]);
$j += 1;
}
}
}
print_r($array);
Since you need to preserve the keys, for loop will throw a notice when an element is not set. This is why we first check if an element exists.
Then the loop looks for two identical values that are consecutive i.e. $i and $i+1. Once it finds them, it enters a while loop to test for 3 or more consecutive identical values. It will only unset a consecutive item if there is at least one occurrence before it and one after it. For example, it will delete $i+2 only if $i+3 is identical.
Hope this helps!

You can approach this as
$r = [];
$lastKey = '';
foreach($array as $k => $v){
if(in_array($v['value'], array_column($r, 'value'))){
$lastKey = $v['key'];
}else{
if($lastKey && !in_array($lastKey, array_column($r, 'key'))){
end($r);
$r[] = [ 'key' => $lastKey, 'value' => $r[key($r)]['value']];
}
$r[] = [ 'key' => $v['key'] , 'value' => $v['value'] ];
$lastKey = $v['key'];
}
}
https://3v4l.org/f6FQv

Here is the solution:
Your array is something like this:
$array = [
["key" => 0, "value" => 25],
["key" => 1, "value" => 25],
["key" => 2, "value" => 25],
["key" => 3, "value" => 33],
["key" => 4, "value" => 45],
["key" => 5, "value" => 66],
["key" => 6, "value" => 66],
["key" => 7, "value" => 66],
["key" => 8, "value" => 66],
["key" => 9, "value" => 55],
];
first, find the first and last occurrence of each value.
You need a method that travels through the array and find the exact value.
Look at this:
function search($search, $array)
{
foreach ($array as $key => $val) {
if ($val['value'] === $search) {
return $key;
}
}
return null;
}
Running $firstOccurrence = search(25, $array) will find the first occurrence of 25.
Now, for finding the index of the last occurrence, we should reverse array to traveling from the end of the array. So $lastOccurrence = search(25, array_reverse($array, true)) will find last occurrence index of 25.
Ok, When we process each value, so, We should not process it again. So we need an array which will hold values which are processed.
Final Code:
function testArray()
{
$array = [
["key" => 0, "value" => 25],
["key" => 1, "value" => 25],
["key" => 2, "value" => 25],
["key" => 3, "value" => 33],
["key" => 4, "value" => 45],
["key" => 5, "value" => 66],
["key" => 6, "value" => 66],
["key" => 7, "value" => 66],
["key" => 8, "value" => 66],
["key" => 9, "value" => 55],
];
$processedItems = [];
$newArray = [];
foreach ($array as $index => $item) {
if (in_array($item["value"], $processedItems))
continue;
$processedItems[] = $item["value"];
$firstIndex = search($item["value"], $array);
$lastIndex = search($item["value"], array_reverse($array, true));
$newArray[$firstIndex] = $array[$firstIndex];
if ($firstIndex != $lastIndex)
$newArray[$lastIndex] = $array[$lastIndex];
}
print_r($newArray);
}
function search($search, $array)
{
foreach ($array as $key => $val) {
if ($val['value'] === $search) {
return $key;
}
}
return null;
}

Please try this hope it's work
for ($i = 0; $i < count($array); $i++) {
if ($array[$i]['value'] == $array[$i+1]['value']) {
$j = 1;
while ($array[$i]['value'] == $array[$i+$j+1]['value']) {
echo $array[$i]['value'].'==='.$array[$i+$j+1]['value'];
unset($array[$i+$j]);
$j += 1;
}
}
}

Related

multidimensional array php - sum values with same groupRange

I will try to explain my problem in small examples:
I have a multidimensional array that represents data from the database, lets's say the input looks like this:
Array
(
[0] => Array
(
[groupRange] => 20-25
[value] => 12
[followersFemaleRate] => 12
[followersMaleRate] => 14
)
[1] => Array
(
[groupRange] => 30-44
[value] => 32
[followersFemaleRate] => 17
[followersMaleRate] => 3
)
[2] => Array
(
[groupRange] => 30-44
[value] => 88
[followersFemaleRate] => 17
[followersMaleRate] => 3
)
)
What I want? To sum value, followersFemaleRate, followersMaleRate with the same groupRange, so the output should be this:
Array
(
[0] => Array
(
[groupRange] => 20-25
[value] => 12
[followersFemaleRate] => 12
[followersMaleRate] => 14
)
[1] => Array
(
[groupRange] => 30-44
[value] => 120
[followersFemaleRate] => 34
[followersMaleRate] => 6
)
)
My code:
$RangeArray = [];
foreach($dbProfile->getData() as $d) {
foreach ($d->getGroupPercentages() as $x){
$ageRangeSingleArray['groupRange'] = $x->getGroupRange();
$ageRangeSingleArray['value'] = $x->getValue();
$ageRangeSingleArray['followersFemaleRate'] = $x->getFollowerGenderFemale();
$ageRangeSingleArray['followersMaleRate'] = $x->getFollowerGenderMale();
$RangeArray [] = $ageRangeSingleArray;
}
}
However im stuck, my idea is to first check if groupRage already exists, if yes, sum values for that range, if not add new element groupRange with values, any help with code?
#Salines solution was good, but I offer a simple solution for the beginners...
Another simple solution to your problem:
$input = [
[
'groupRange' => '20-25',
'value' => 12,
'followersFemaleRate' => 12,
'followersMaleRate' => 14,
],
[
'groupRange' => '30-44',
'value' => 88,
'followersFemaleRate' => 17,
'followersMaleRate' => 3,
],
[
'groupRange' => '30-44',
'value' => 32,
'followersFemaleRate' => 17,
'followersMaleRate' => 3,
],
];
$groupRangeHolder = [];
$output = [];
foreach($input as $item) {
if( ! array_key_exists( $item['groupRange'] , $groupRangeHolder ) )
{
$groupRangeHolder[$item['groupRange']]['value'] = $item['value'];
$groupRangeHolder[$item['groupRange']]['followersFemaleRate'] = $item['followersFemaleRate'];
$groupRangeHolder[$item['groupRange']]['followersMaleRate'] = $item['followersMaleRate'];
}
else
{
$groupRangeHolder[$item['groupRange']]['value'] += $item['value'];
$groupRangeHolder[$item['groupRange']]['followersFemaleRate'] += $item['followersFemaleRate'];
$groupRangeHolder[$item['groupRange']]['followersMaleRate'] += $item['followersMaleRate'];
}
}
$cur = 0;
foreach($groupRangeHolder as $key => $values)
{
$output[$cur]['groupRange'] = $key;
$output[$cur]['value'] = $values['value'];
$output[$cur]['followersFemaleRate'] = $values['followersFemaleRate'];
$output[$cur++]['followersMaleRate'] = $values['followersMaleRate'];
}
echo "<pre>";
print_r($output);
echo "</pre>";
try:
$input = [
[
'groupRange' => '20-25',
'value' => 12,
'followersFemaleRate' => 12,
'followersMaleRate' => 14,
],
[
'groupRange' => '30-44',
'value' => 88,
'followersFemaleRate' => 17,
'followersMaleRate' => 3,
],
[
'groupRange' => '30-44',
'value' => 32,
'followersFemaleRate' => 17,
'followersMaleRate' => 3,
],
];
$groupedArray = [];
foreach( $input as $item ){
$groupedArray[$item['groupRange']]['groupRange'] = $item['groupRange'];
$groupedArray[$item['groupRange']]['value'] = ($groupedArray[$item['groupRange']]['value'] ?? 0) + $item['value'];
$groupedArray[$item['groupRange']]['followersFemaleRate'] = $item['followersFemaleRate'];
$groupedArray[$item['groupRange']]['followersMaleRate'] = $item['followersMaleRate'];
}
$output = array_values($groupedArray);
print_r($output);
output:
Array
(
[0] => Array
(
[groupRange] => 20-25
[value] => 12
[followersFemaleRate] => 12
[followersMaleRate] => 14
)
[1] => Array
(
[groupRange] => 30-44
[value] => 120
[followersFemaleRate] => 17
[followersMaleRate] => 3
)
)

Counting values in multidimensional array to new array

I currently have the following array:
Array
(
[0] => Array
(
[declaration_value] => 1
[date] => 2018-07-16
[client_id] => 3
[declaration_id] => 12
)
[1] => Array
(
[declaration_value] => 3
[date] => 2018-07-16
[client_id] => 3
[declaration_id] => 12
)
)
how can i make to get the following array result: (count declaration_value if the same date/client_id/declaration_id )
Array
(
[0] => Array
(
[declaration_value] => 4
[date] => 2018-07-16
[client_id] => 3
[declaration_id] => 12
)
)
$listdb = [
["declaration_value" => 1, "date" => "2018-07-16", "client_id" => 3, "declaration_id" => 12],
["declaration_value" => 2, "date" => "2018-07-16", "client_id" => 2, "declaration_id" => 12],
["declaration_value" => 2, "date" => "2018-07-16", "client_id" => 2, "declaration_id" => 12],
["declaration_value" => 8, "date" => "2018-07-17", "client_id" => 2, "declaration_id" => 12],
["declaration_value" => 3, "date" => "2018-07-16", "client_id" => 3, "declaration_id" => 12],
];
$sameKeys = ["date", "client_id", "declaration_id"];
$sumKeys = ["declaration_value"];
print_r(sum_my($listdb, $sameKeys, $sumKeys));
function sum_my(array $listdb = [], array $sameKeys = [], array $sumKeys = []): array {
$newdb = [];
if (empty($listdb) === true || empty($sameKeys) === true || empty($sumKeys) === true) {
return $newdb;
}
foreach ($listdb as $value) {
$ckKey = "";
foreach ($sameKeys as $sameKey) {
$ckKey .= $value[$sameKey];
}
if (isset($newdb[$ckKey])) {
foreach ($sumKeys as $sumKey) {
$newdb[$ckKey][$sumKey] += $value[$sumKey];
}
} else {
$newdb[$ckKey] = $value;
}
}
return $newdb;
}
Thank you for your tips, I solved it.

PHP: Is there a command that merges arrays of the same key and sums content with the same keys

I have 2 arrays of arrays which I want to merge by keys for the first step and them sum on the second step - example:
Array
(
[2017-03-01] => Array
(
[apples] => 2
[bananas] => 1
)
[2017-03-02] => Array
(
[apples] => 3
[bananas] => 6
)
[2017-03-03] => Array
(
[apples] => 0
[bananas] => 4
)
}
Array
(
[2017-03-01] => Array
(
[apples] => 3
[bananas] => 2
)
[2017-03-02] => Array
(
[apples] => 4
[bananas] => 7
)
[2017-03-03] => Array
(
[apples] => 1
[bananas] => 5
)
}
Wanted result:
Array
(
[2017-03-01] => Array
(
[apples] => 5
[bananas] => 3
)
[2017-03-02] => Array
(
[apples] => 7
[bananas] => 13
)
[2017-03-03] => Array
(
[apples] => 1
[bananas] => 9
)
}
Is there a command that does that (as a 1 single command) that will avoid looping through the arrays?
No. (obligatory additional characters)
Here's an insanely inefficient way of doing but without using any sort of for foreach or while
$result = array_map(function ($aentry, $key) use ($b) {
$bentry = $b[$key] ?? [];
$result = array_map(function ($value, $key) use ($bentry) {
return [$key, $value + ($bentry[$key] ?? 0) ];
},$aentry, array_keys($aentry));
return [ $key, array_combine(array_column($result, 0), array_column($result, 1)) ];
}, $a,array_keys($a));
$result = array_combine(array_column($result, 0), array_column($result, 1));
Example: http://sandbox.onlinephpfunctions.com/code/4c1dca3057c33dd17d0106666a497c7b08e57038
Solution without for/foreach/... , assuming that all keys are the same, you can do:
$array1 = [
'2017-03-01' => [
'apples' => 2,
'bananas' => 1,
],
'2017-03-02' => [
'apples' => 3,
'bananas' => 6,
],
'2017-03-03' => [
'apples' => 0,
'bananas' => 4,
],
];
$array2 = [
'2017-03-01' => [
'apples' => 3,
'bananas' => 2,
],
'2017-03-02' => [
'apples' => 4,
'bananas' => 7,
],
'2017-03-03' => [
'apples' => 1,
'bananas' => 5,
],
];
array_walk($array1, function(&$subarray1, $key) use($array2) {
array_walk($subarray1, function(&$element, $subkey) use($array2, $key) {
$element += $array2[$key][$subkey];
});
});
Not good performance, just for fun.
Thank you all for your answers, here is my code:
function merge_fruit_data($new_data, $old_data){
// If it's the first time running - return new data as an array
if (empty($old_data)){
return $new_data;
}
else {
foreach ( $new_data as $key => $insert_new_data ) {
if ( !$old_data[$key] ) {
$old_data[$key] = $insert_new_data;
}
else{
$old_data[$key]['apples'] += $insert_new_data['apples'];
$old_data[$key]['bananas'] += $insert_new_data['bananas'];
}
}
}
return $old_data;
}
Efficiency comments are welcome.
This may help you
`$a = array('2017-03-01' => array('apples'=> 2, 'bananas'=>1),
'2017-03-02' => array('apples'=> 3, 'bananas'=>6),
'2017-03-03' => array('apples'=> 0, 'bananas'=>4));
$b=array('2017-03-01' => array('apples'=> 3, 'bananas'=>2),
'2017-03-02' => array('apples'=> 4, 'bananas'=>7),
'2017-03-03' => array('apples'=> 1, 'bananas'=>5));
$sumArray = array();
foreach ($a as $key=>$value) {
$sumArray[$key]['apples']=($a[$key]['apples']+$b[$key]['apples']);
$sumArray[$key]['bananas']=($a[$key]['bananas']+$b[$key]['bananas']);
}
print_r($sumArray);
`

Extract a row by value from php array

This is my array:
Array (
[0] => Array ( [SocketID] => 1 [SocketName] => Name [SocketDecimal] => 0 [SocketHex] => 00 [SocketAtt] => 1 [Category] => 1 [Value] => 100 [Procentage] => 0 )
[1] => Array ( [SocketID] => 2 [SocketName] => Name2 [SocketDecimal] => 50 [SocketHex] => 32 [SocketAtt] => 1 [Category] => 1 [Value] => 800 [Procentage] => 0 )
[2] => Array ( [SocketID] => 3 [SocketName] => Name3 [SocketDecimal] => 100 [SocketHex] => 64 [SocketAtt] => 1 [Category] => 1 [Value] => 60 [Procentage] => 0 )
)
How can I extract a row by SocketDecimal?
For example: I want to extract row where SocketDecimal = 50 and make new an array only with that row.
foreach($array as $entry) {
if($entry['SocketDecimal'] == 50)
$newArr[] = $entry;
}
$newArr will contain the desired "row". Of course you can manipulate the if-statement depending on which "row" (I'd just call it array entry) you want to extract.
It's not the best way for big data! It's easy for deep multiarrays.
$arr = array(
array('socket_id'=>1,'name'=>'test1'),
array('socket_id'=>2,'name'=>'test2'),
array('socket_id'=>3,'name'=>'test3'),
array('socket_id'=>2,'name'=>'test4')
);
$newArr = array();
foreach($arr as $row){
foreach($row as $key=>$r){
if($key == 'socket_id' && $r==2)
$newArr[] = $row;
}
}
print_r($newArr);
$result = array();
foreach($input as $i){
if($i['SocketDecimal']==50)
$result[]=$i;
}
You can do it by this method
foreach ($yourarray as $key => $value){
$newarray = array("SocketDecimal"=>$value["SocketDecimal"];
}
print_r($newarray);
If your result array is like given below
$arr = array(
array( 'SocketID' => 1, 'SocketName' => 'Name', 'SocketDecimal' => 0, 'SocketHex' => 0, 'SocketAtt' => 1, 'Category' => 1, 'Value' => 100, 'Procentage' => 0 ),
array ( 'SocketID' => 2, 'SocketName' => 'Name2', 'SocketDecimal' => 50, 'SocketHex' => 32, 'SocketAtt' => 1, 'Category' => 1, 'Value' => 800, 'Procentage' => 0 ),
array ( 'SocketID' => 3, 'SocketName' => 'Name3', 'SocketDecimal' => 100, 'SocketHex' => 64, 'SocketAtt' => 1, 'Category' => 1, 'Value' => 60, 'Procentage' => 0 )
);
print_r($arr);
Get row for SocketDecimal=50 by following loop:
<pre>
$resultArr = '';
foreach($arr as $recordSet)
{
if($recordSet['SocketDecimal'] == 50)
{
$resultArr[] = $recordSet;
break;
}
}
</pre>
print_r($resultArr);
break foreach loop so that it will not traverse for all the array when SocketDecimal(50) founded.
You can use array_column + array_search combo
$array = Array (
"0" => Array ( "SocketID" => 1, "SocketName" => "Name", "SocketDecimal" => 0, "SocketHex" => 00, "SocketAtt" => 1, "Category" => 1, "Value" => 100, "Procentage" => 0 ) ,
"1" => Array ( "SocketID" => 2, "SocketName" => "Name2", "SocketDecimal" => 50, "SocketHex" => 32, "SocketAtt" => 1, "Category" => 1, "Value" => 800, "Procentage" => 0 ),
"2" => Array ( "SocketID" => 3, "SocketName" => "Name3", "SocketDecimal" => 100, "SocketHex" => 64, "SocketAtt" => 1, "Category" => 1, "Value" => 60 ,"Procentage" => 0 )
);
var_dump($array[array_search(50,array_column($array,'SocketDecimal'))]);

Remove element from array in php

I am new to php and i want to remove element from array Here is my array:
Array
(
[Total] => 21600000
[Items] => Array
(
[2-13] => Array
(
[Item] => 2
[PID] => 13
[UPrice] => 11000000
[Qty] => 1
[Total] => 11000000
)
[58-167] => Array
(
[Item] => 58
[PID] => 167
[UPrice] => 5300000
[Qty] => 1
[Total] => 5300000
)
)
)
And i want to remove array element by PID.
I have try this but no luck:-
$ShoppingBag =$_SESSION['ssss'];
if ($ShoppingBag !== null && $ShoppingBag['Total'] > 0) {
foreach ($ShoppingBag['Items'] as $IOrder) {
if($IOrder["PID"]==13)
{
unset($ShoppingBag[$IOrder]);
}else
{
}
}
}
Please help. Thanks
You can try with one simple array map :)
$arr = [
'Total' => 21600000,
'Items' => [
'2-13' => [
'Item' => 2,
'PID' => 13,
'UPrice' => 11000000,
'Qty' => 1,
'Total' => 11000000
],
'58-167'=> [
'Item' => 58,
'PID' => 167,
'UPrice' => 5300000,
'Qty' => 1,
'Total' => 5300000
]
]
];
$test = array_map(function($ar) {
foreach($ar as $k=>$i) {
if( isset($i['PID']) && $i['PID'] == '13')
unset($ar[$k]);
}
return $ar; } , $arr);
var_dump($test);
You need 2 loop to do the action you want.
foreach($my_array as $key=>$value)
{
if(is_array($value))
{
foreach($value as $k=>$v)
{
if($k == 'PID')
{
unset($value[$k]);
}
}
}
}
with this you can remove only element with key PID.
Hi youre unsetting the $IOrder instead of the Item that you want to delete:
This code is a solution an i tested it :
$ShoppingBag = Array
(
"Total" => 21600000,
"Items" => Array
(
"2-13" => Array
(
"Item" => 2,
"PID" => 13,
"UPrice" => 11000000,
"Qty" => 1,
"Total" => 11000000,
),
"58-167" => Array
(
"Item" => 58,
"PID" => 167,
"UPrice" => 5300000,
"Qty" => 1,
"Total" => 5300000,
),
),
);
foreach($ShoppingBag["Items"] as $key => $value){
if($value["PID"]==13){
unset($ShoppingBag["Items"][$key]);
}
}
You should know that always when you're using foreach loop the foreach( $a as $b ) when you do something to $b , $a remains the same because tey are different variables :)
Hope it will help you .
Regards.
$arr = [
'Total' => 21600000,
'Items' => [
'2-13' => [
'Item' => 2,
'PID' => 13,
'UPrice' => 11000000,
'Qty' => 1,
'Total' => 11000000
],
'58-167'=> [
'Item' => 58,
'PID' => 167,
'UPrice' => 5300000,
'Qty' => 1,
'Total' => 5300000
]
]
];
$pid_to_remove = 13;
$new_ar = array_filter(
$arr,
function ($v) using ($pid_to_remove) {
return (!isset($v['PID'])) || ($v['PID'] != $pid_to_remove);
}
);

Categories