I have the following two stdClass array from a loop. Now I need to merge them when when the key 'id' matches.
array (size=1)
0 =>
object(stdClass)[28]
public 'id' => string '78' (length=2)
public 'quantity' => string '5' (length=1)
array (size=1)
1 =>
object(stdClass)[31]
public 'product_id' => string '78' (length=2)
public 'quantity' => string '1' (length=1)
So the final array become
array (size=1)
1 =>
object(stdClass)[31]
public 'product_id' => string '78' (length=2)
public 'quantity' => string '6' (length=1)
Any help on how to do that ? I decode the original data using json_decode from [{"id":"78","quantity":"1"}] this format of data.
If you add an extra parameter to the json_decode, you can get the data as an associative array, which is much easier to work with. I've done a couple of versions ( the first is PHP 7 ), pick one which works with your system.
<?php
error_reporting ( E_ALL );
ini_set ( 'display_errors', 1 );
$arr1 = json_decode('[{"id":"78","quantity":"1"}, {"id":"79","quantity":"3"}]', true);
$arr2 = json_decode('[{"id":"78","quantity":"5"}]', true);
$arr3 = array_merge($arr1, $arr2);
// V7
$result = [];
foreach ( $arr3 as $element ) {
$result[$element['id']] = ($result[$element['id']]??0)
+ $element['quantity'];
}
print_r($result);
// Prior to V7
$result = array();
foreach ( $arr3 as $element ) {
if ( !isset($result[$element['id']]) ){
$result[$element['id']] = 0;
}
$result[$element['id']] += $element['quantity'];
}
print_r($result);
I've added another element to show how this adds up, but the output of this is...
Array
(
[78] => 6
[79] => 3
)
Array
(
[78] => 6
[79] => 3
)
Here is a solution that maintains the format in your original question.
It also uses array_reduce which is a concise way to process an array.
<?php
$input1 = '[{"id":"78","quantity":"7800"},
{"id":"79","quantity":"7900"},
{"id":"80","quantity":"8000"}]';
$input2 = '[{"id":"78","quantity":"6"},
{"id":"79","quantity":"8"},
{"id":"80","quantity":"6"},
{"id":"81","quantity":"7"}]';
$input1Arr = json_decode($input1);
$input2Arr = json_decode($input2);
$combinedArrays = array_merge($input1Arr, $input2Arr);
echo "combinedArrays = " . print_r($combinedArrays, true) . "\n";
$result = array_reduce($combinedArrays,
function($intermediateResult, $item){
if ( ! array_key_exists($item->id, $intermediateResult) ) {
// First time encountering an object with this id
$intermediateResult[$item->id] = $item;
}
else {
// We have an object with this id already so just add the quantity
$intermediateResult[$item->id]->quantity += $item->quantity;
}
return $intermediateResult;
}, []);
// Get the values from the result array
print_r(array_values($result));
Related
I have a php array like this
print_r(myarray) is
Array ( [0] => Array ( [#xsi:nil] => true ) [1] => Array ( [#xsi:nil] => true ) [2] => Array ( [#xsi:nil] => true ) [3] => 'some value' [4] => Array ( [#xsi:nil] => true ))
I need to eliminate the values Array ( [#xsi:nil] => true ) or just to replace them with say "nill". I tried a lot, this being a nested array i couldnt get the key for the values [#xsi:nil] => true
How to check in php for the indexes which hold the value Array ( [#xsi:nil] => true )? and replace them with say 'nill'?
trial one :
$key1 = array_search(array('#xsi:nil'=>'true'), array_column($arrays, 'NOTE')); //to catch the indexes.
function searchMyCoolArray($arrays, $key, $search) {
$count = 0;
foreach($arrays as $object) {
if(is_object($object)) {
$ob1 = $object;
$object = get_object_vars($object);
$key1 = array_search(40489, array_column($arrays, 'uid'));
}
if(array_key_exists($key, $object) && $object[$key] == $search)
{
// print_r($first_names_note[$key]);
// echo "ffgfg ".$ob1[0]." rtrtrt";
// var_dump($object);
// print_r($arrays[$key]);
// echo $object;
// print_r($object);
// print_r($first_names_note)."<br>";
$count++;
//echo "sddsdsdsd";
}
}
return $count;
}
echo searchMyCoolArray($first_names_note, '#xsi:nil', 'true');
here i got the count correct, but it was not i need, I tried to get the indexs in the function itself, but failed
Please help, i googled alot pleeeeeeeeeeeeeeeeez
You may try to use array_walk to traverse the array and then unset all elements with the key #xsi:nil like this:
<?php
$arr = array(
array("#xsi:nil" => true),
array("#xsi:nil" => true),
array("#xsi:nil" => true),
array("some_value" =>4),
array("#xsi:nil" => true),
);
array_walk($arr, function(&$data){
if(is_array($data) && array_key_exists("#xsi:nil", $data)){
unset($data["#xsi:nil"]);
$data[] = "nil";
}
});
var_dump($arr);
// IF YOU WANT TO REMOVE ALL EMPTY ARRAYS COMPLETELY, JUST DO THIS:
$arr = array_filter($arr);
var_dump($arr);
// GET THE LENGTH OF THE FILTERED ARRAY.
$count = count($arr);
echo $count; //<== PRODUCES 5
// THE 1ST VAR_DUMP() PRODUCES:
array (size=5)
0 =>
array (size=1)
0 => string 'nil' (length=3)
1 =>
array (size=1)
0 => string 'nil' (length=3)
2 =>
array (size=1)
0 => string 'nil' (length=3)
3 =>
array (size=1)
'some_value' => int 4
4 =>
array (size=1)
0 => string 'nil' (length=3)
// THE 2ND VAR_DUMP() PRODUCES:
array (size=5)
0 =>
array (size=1)
0 => string 'nil' (length=3)
1 =>
array (size=1)
0 => string 'nil' (length=3)
2 =>
array (size=1)
0 => string 'nil' (length=3)
3 =>
array (size=1)
'some_value' => int 4
4 =>
array (size=1)
0 => string 'nil' (length=3)
Test it out HERE.
Cheers & Good Luck...
This is not the answer, the code for the answer was provided by #Poiz
Here is my complete code which i formatted
//my array
$arr = Array (Array ( '#xsi:nil' => 'true' ), Array ('#xsi:nil' => 'true' ), Array ( '#xsi:nil' => 'true' ) );
// print_r($arr);
//performed array walk
array_walk($arr, function(&$data){
if(is_array($data) && array_key_exists("#xsi:nil", $data)){
unset($data["#xsi:nil"]);
$data = "nil";
}
});
print_r($arr);
//OUTPUT : Array ( [0] => nil [1] => nil [2] => nil )
This question already has answers here:
How can I sort arrays and data in PHP?
(14 answers)
Closed 6 years ago.
One of my function return this array... Yes I have seen other examples here on SO but non where able to solve my problem.
array (size=4)
0 =>
array (size=2)
'refferrer' => string 'http://google.com/' (length=18)
'number_of_reffers' => string '15' (length=2)
1 =>
array (size=2)
'refferrer' => string 'https://facebook.com/' (length=21)
'number_of_reffers' => string '22' (length=2)
2 =>
array (size=2)
'refferrer' => string 'none' (length=4)
'number_of_reffers' => string '74' (length=2)
3 =>
array (size=2)
'refferrer' => string 'http://findy.com/' (length=17)
'number_of_reffers' => string '6' (length=1)
I will like to know how to sort this array in descending and asscending order using the
'number_of_reffers'...
What I am trying to say is that i want the one with the hishest number_of_reffers to come first, follow by the next and so on.
Is this possible and how can i do this in php.
Thanks for you help.
You need usort
Given your array, you would then do this:
usort( $array, 'sort_by_referrer_count' );
var_dump($array);
// This will sort ascending
function sort_by_referrer_count( $a, $b ) {
// Some defensive coding to ensure keys exist
$a = ( isset( $a['number_of_referrers'] ) ) ? $a['number_of_referrers'] : 0;
$b = ( isset( $b['number_of_referrers'] ) ) ? $b['number_of_referrers'] : 0;
if ($a == $b) {
return 0;
}
return ( $a < $b ) ? -1 : 1;
}
If you want descending, then you could do this (using the same function above):
usort( $array, 'sort_by_referrer_count' );
$array = array_reverse( $array );
In the most simplest sense; you may just want to try this:
<?php
// SORTING ALGORITHM:
// TO SORT IN THE OPPOSITE SENSE...
// (IE. ASCENDING [AS OPPOSED TO THE DEFAULT: DESCENDING]
// CHANGE THE LESS THAN (<) BELOW TO GREATER THAN (>)
function orderByNumRef($arrPrev, $arrNext) {
if ($arrPrev['number_of_reffers'] == $arrNext['number_of_reffers']) {
return 0;
}
return ($arrPrev['number_of_reffers'] < $arrNext['number_of_reffers']) ? -1 : 1;
}
//GIVEN ARRAY - DYNAMIC OR HARD-CODED
$arr = array(
array(
'refferrer' => 'http://google.com/',
'number_of_reffers' =>'15',
),
array(
'refferrer' => 'https://facebook.com/',
'number_of_reffers' =>'74',
),
array(
'refferrer' => 'http://findy.com/',
'number_of_reffers' =>'6',
),
);
//BEFORE SORTING:
var_dump($arr);
uasort($arr, 'orderByNumRef');
//AFTER SORTING:
var_dump($arr);
Hope it helps...
Try this:
<?php
$my_array;
//Sort Acceding
usort($my_array, create_function('$a,$b', 'return (Int)$a["number_of_reffers"]-(Int)$b["number_of_reffers"];'));
//Or sort Descending
usort($my_array, create_function('$a,$b', 'return (Int)$b["number_of_reffers"]-(Int)$a["number_of_reffers"];'));
The easiest way I find to do it is by creating a new array with the number_of_reffers as the key. Then sort the new array with either ksort() or krsort(). This in the end leaves the original array intact. Otherwise creating the original array in the intended format would be better.
<?php
// original array
$array = array(
array('refferrer' => 'http://google.com/', 'number_of_reffers' => '15'),
array('refferrer' => 'https://facebook.com/', 'number_of_reffers' => '22'),
array('refferrer' => 'none', 'number_of_reffers' => '74'),
array('refferrer' => 'http://findy.com/', 'number_of_reffers' => '6')
);
$foo = array(); // new empty array
// loop through $array, assign the number_of_reffers as the key for the refferrer
foreach ($array as $key => $bar) {
$foo[$bar['number_of_reffers']] = $bar['refferrer'];
}
/*
new array will be:
array(
'15' => 'http://google.com/',
'22' => 'https://facebook.com/'
etc .....
)
*/
// use Ksort / Krsort to sort the key asc or desc
ksort($foo); // ascending order
#krsort($foo); // descending order
die('<pre>'.print_r($foo, true).'</pre>'); // pretty printing of sorted array
?>
As a function ....
<?php
Function Referrer_sort($array, $asc = true) {
IF (!is_array($array)) { return 'not an array'; }
$result = array();
foreach ($array as $key => $value) {
$result[$value['number_of_reffers']] = $value['refferrer'];
}
switch ($asc) {
case false: krsort($result); return $result;
default: ksort($result); return $result;
}
}
$foo_asc = Referrer_sort($array);
$foo_desc = Referrer_sort($array, false);
die('<pre>Ascending:<br>'.print_r($foo_asc, true).'<br>Descending:<br>'.print_r($foo_desc, true).'</pre>');
?>
Changing the original array
Modifying the original array by changing the index key with the value of number_of_reffers.
<?php
Function Rebuild_Referrer_sort($array, $asc = true) {
IF (!is_array($array)) { return 'not an array'; }
$result = array();
foreach ($array as $key => $value) {
$result[$value['number_of_reffers']] = array('refferrer' => $value['refferrer'], 'number_of_reffers' => $value['number_of_reffers']);
}
switch ($asc) {
case false: krsort($result); return $result;
default: ksort($result); return $result;
}
}
$foo_asc = Rebuild_Referrer_sort($array);
$foo_desc = Rebuild_Referrer_sort($array, false);
die('<pre>Ascending:<br>'.print_r($foo_asc, true).'<br>Descending:<br>'.print_r($foo_desc, true).'</pre>');
/**
Returns:
Ascending:
Array
(
[6] => Array
(
[refferrer] => http://findy.com/
[number_of_reffers] => 6
)
[15] => Array
(
[refferrer] => http://google.com/
[number_of_reffers] => 15
)
[22] => Array
(
[refferrer] => https://facebook.com/
[number_of_reffers] => 22
)
[74] => Array
(
[refferrer] => none
[number_of_reffers] => 74
)
)
Descending:
Array
(
[74] => Array
(
[refferrer] => none
[number_of_reffers] => 74
)
[22] => Array
(
[refferrer] => https://facebook.com/
[number_of_reffers] => 22
)
[15] => Array
(
[refferrer] => http://google.com/
[number_of_reffers] => 15
)
[6] => Array
(
[refferrer] => http://findy.com/
[number_of_reffers] => 6
)
)
*/
?>
I have a huge, complicated issue in my php app. Here are the details:
I currently have this as my array (var dumped):
array (size=6)
0 => string '11/04/15' (length=8)
1 => string '15/04/15' (length=8)
2 => string '19/04/15' (length=8)
3 => string '1' (length=1)
4 => string '1' (length=1)
5 => string '3' (length=1)
But I want it displayed as:
array (size=6)
array(size=2)
string '11/04/15' (length=8)
string '1' (length=1)
array(size=2)
string '15/04/15' (length=8)
string '1' (length=1)
array(size=2)
string '19/04/15' (length=8)
string '3' (length=1)
As you can see I would like to add sub arrays, reorder the structure and remove the keys. The starter array values change so there could be more dates/less dates and numbers. Also the its linked, the key 0 should be bulked with key 3 and key 1 bulked with key 4 etc. I think that's enough information.
PS: I'm trying to arrange the data for Chart PHP's Bar Graph (http://www.chartphp.com/).
My approach would be the following:
Go through the array values with a foreach-loop and find out when the first number starts (in this case, it's the 4. element)
Save the number inside of a variable.
Create a new array
Go through the old array again and get the pairs, then push them into the new array.
The code would be similar to this:
<?
$old = array("date1","date2","date3",1,2,3);
$n = null;
foreach($old as $k => $v){
if(/*CHECK HERE IF $v is NOT A DATE anymore*/){
$n = $k;
break;
}
}
$new = array();
foreach($old as $k => $v){
if($k < $n){
$temp = array($v, $old[$k+$n]);
array_push($new, $temp);
}
}
var_dump ($new);
?>
This should work for you:
Since it is pretty obvious I'm going to assume, that the pattern behind your expected results should be to combine the numbers with the dates which are sorted ASC.
So here I first get all dates into an array with preg_grep(). Then I also get the numbers by getting the array_diff() from the original array and the dates array.
Then I sort both arrays ASC and the $dates array I sort with usort() where I compare the timestampes which I get with strtotime() and the $numbers array I sort simply with sort().
At the end I simply loop through both arrays with array_map() where I then create the expected result.
<?php
$arr = [
"19/04/15",
"11/04/15",
"15/04/15",
"3",
"1",
"1",
];
$dates = preg_grep("/\d{2}\/\d{2}\/\d{2}/", $arr);
$numbers = array_diff($arr, $dates);
sort($numbers);
usort($dates, function($a, $b){
if(strtotime($a) == strtotime($b))
return 0;
return strtotime($a) < strtotime($b) ? 1 : -1;
});
$result = array_map(function($v1, $v2){
return [$v1, $v2];
}, $dates, $numbers);
print_r($result);
?>
output:
Array
(
[0] => Array
(
[0] => 11/04/15
[1] => 1
)
[1] => Array
(
[0] => 15/04/15
[1] => 1
)
[2] => Array
(
[0] => 19/04/15
[1] => 3
)
)
I've got an array that looks like this:
'coilovers' =>
'strut_and_individual_components' =>
'complete_strut' =>
0 =>
array (size=5)
'achse' => string 'Oś tylnia' (length=10)
'position' => string 'Prawo' (length=5)
'material' => string 'Stal' (length=4)
'variante' => string 'Wariant 3' (length=9)
'img' => string 'gewindefahrwerk_federbein_komplett_level3.png'
'hls_components' =>
'assembly_pump_unit' =>
0 =>
'achse' => string 'Assembly pump unit' (length=18)
'img' => string 'hls_komponenten_baugruppe_pumpeneinheit_level3.png'
Now I'm getting string parameter that looki for example like : [coilovers][strut_and_individual_components][complete_strut][0]
And now I want to to unset whole branch of that array based on that parameter. So far I've accomplished how to read value but that parameter and it looks like.
private function str_index_array(&$arr, $indexes) {
$arr_indexes = explode('][',trim($indexes,'[]'));
$session_array = &$arr;
foreach($arr_indexes as $index) {
$session_array = &$session_array[$index];
}
}
But I'm stuck now, I need to check if that element is last element in array and in previous element is that previous element is empty if its empty unset whole brunch. Any ideas?
I'm sure some PHP/array/reference expert can come up with better ways of doing this, but here is one bug-ugly solution. I've set up a loop to obtain a reference to the last but second level index, and test and delete the sub-indexes from there. Note that there is no error-checking to test if the indexes actually exist before using them.
<?php
$a = array (
'coilovers' => array (
'strut_and_individual_components' => array (
'complete_strut' => array (
0 => array (
'achse' => 'Os tylnia',
'position' => 'Prawo',
'material' => 'Stal',
'variante' => 'Wariant 3',
'img' => 'gewindefahrwerk_federbein_komplett_level3.png'
)
)
)
),
'hls_components' => array (
'assembly_pump_unit' => array (
0 => array (
'achse' => 'Assembly pump unit',
'img' => 'hls_komponenten_baugruppe_pumpeneinheit_level3.png'
)
)
)
);
function delete_index (&$arr, $indexes) {
$arr_indexes = explode('][',trim($indexes,'[]'));
for ($i = 0; $i < count($arr_indexes) - 2; $i++) {
$arr = &$arr[$arr_indexes[$i]];
}
$ix1 = $arr_indexes[$i];
$ix2 = $arr_indexes[$i+1];
unset ($arr[$ix1][$ix2]);
if (empty ($arr[$ix1]))
unset ($arr[$ix1]);
}
print_r ($a);
delete_index ($a, '[coilovers][strut_and_individual_components][complete_strut][0]');
print_r ($a);
I would like to turn the following string into an array:
prijs=0,209&orderby=price&order=undefined&posts_per_page=undefined
INTO
array(
[prijs] => Array
(
[0] => 0
[1] => 209
)
[orderby] => Array
(
[0] => price
)
[order] => Array
(
[0] => undefined
)
[posts_per_page] => Array
(
[0] => undefined
)
)
Something like that. Is that possible?
Now I'm using some foreach loops, but that's not so fast and ideal like a RegEx.
It's a script which needs to load as fast as possible, so every bit of improvement in the code may help.
The amount of arrays can be variable. But it will always be 2 levels deep, like above. And just one main array.
You don't need REGEX for this. The string you have shown looks like a URL query string, in which case $_GET will already hold the values you need:-
var_dump($_GET);
Should give you:-
array (size=4)
'prijs' => string '0,209' (length=5)
'orderby' => string 'price' (length=5)
'order' => string 'undefined' (length=9)
'posts_per_page' => string 'undefined' (length=9)
Otherwise you can use parse_string().
$values = array();
parse_str('prijs=0,209&orderby=price&order=undefined&posts_per_page=undefined', $values);
var_dump($values);
Output:
array (size=4)
'prijs' => string '0,209' (length=5)
'orderby' => string 'price' (length=5)
'order' => string 'undefined' (length=9)
'posts_per_page' => string 'undefined' (length=9)
Looks like you're in need of array_walk as it should be faster than a foreach even if it does pretty much the same thing it does it at a lower level.
as vascowhite suggested you can use $_GET if you have it or parse_str() to get an initial array, after that:
array_walk($array, function(&$n) {
$n = explode(',', $n);
});
Live code: http://3v4l.org/YfuKs
Results in exactly what you want (always having arrays instead of CSV strings):
Array
(
[prijs] => Array
(
[0] => 0
[1] => 209
)
[orderby] => Array
(
[0] => price
)
[order] => Array
(
[0] => undefined
)
[posts_per_page] => Array
(
[0] => undefined
)
)
PS: instead of explode() you can use preg_split('/,/', $n) since you mentioned RegEx and see which one is faster for you
$str = 'prijs=0,209&orderby=price&order=undefined&posts_per_page=undefined';
$array = preg_split('/[&]/' , $str);
foreach ($array as $a)
{
$a = preg_split('/[=]/' , $a);
$a[1] = preg_split('/[,]/' , $a[1]);
}
var_dump($array);
Well, you can use something like this:
<?php
parse_str("prijs=0,209&orderby=price&order=undefined&posts_per_page=undefined",$myArray);
$myArray['prijs'] = explode(",", $myArray['prijs']);
$myArray['orderby'] = explode(",", $myArray['orderby']);
$myArray['order'] = explode(",", $myArray['order']);
$myArray['posts_per_page'] = explode(",", $myArray['posts_per_page']);
print_r($myArray);
?>
function urlSplitter($input)
{
$step1Array = explode('&', $input);
$result = array();
foreach($step1Array as $element)
{
$parts = explode("=", $element);
$result[$parts[0]] = explode(",", $parts[1]);
}
return $result;
}
$result = urlSplitter("prijs=0,209&orderby=price&order=undefined&posts_per_page=undefined");
var_dump($result);