PHP - transform array into the new one - php

CURRENT ARRAY:
stdClass Object (
[name1] => Someting very useful
[text1] => Description of something useful
[url1] => link.to/useful
[name2] => Someting very useful2
[text2] => Description of something useful2
[url2] => link.to/useful2
[name3] => Someting very useful3
[text3] => Description of something useful3
[url3] => link.to/useful3
)
I NEED:
To create multidimensional array where keys like name1, text1, url1 (and so on) will be putted into own array. How to accomplish that?

I think you want:
$array = array_chunk((array)$object, $chunkSize = 3, $preserveKeys = true);
($object is your object above)
This will cast your object to an array, and split it into smaller arrays of 3 elements each

Well;
$array = (array) $object;

$array = array();
$c = count($object) / 3;
(Array) $object;
for($i = 1; $i <= $c; $i++){
$array[$i]['name' + $i] = $object['name' + $i];
$array[$i]['text' + $i] = $object['text' + $i];
$array[$i]['url' + $i] = $object['url' + $i];
}

This would be very versatile even if you don't have consistent input, like exactly three properties per child. Also the properties in the object don't have to be in any particular order.
//$obj is the object you have in the question
$objects = array();
foreach($obj as $key => $val) {
$result = preg_match('%([a-zA-Z]+)([0-9]+)%', $key,$matches);
$new_key = $matches[2];
$property = $matches[1];
if(!isset($objects[$new_key])) {
$objects[$new_key] = array();
}
$objects[$new_key][$property] = $val;
}

Related

Sum values from two objects where properties are the same

How can I merge two objects and sum the values of matching properties? I am hoping for a built in function in PHP, otherwise I am seeking an easy way of doing it.
See code under, where I have $objectA and $objectB which I want to become $obj_merged.
$objectA = (object) [];
$objectA->a = 1;
$objectA->b = 1;
$objectA->d = 1;
$objectB = (object) [];
$objectB->a = 2;
$objectB->b = 2;
$objectB->d = 2;
$obj_merged = (object) [
'a' => 3,
'b' => 3,
'd' => 3
];
What you want to achieve is a sum of the properties. A merge would overwrite the values. There is no built-in PHP function to do this with objects.
But you can use a simple helper function where you could put in as many objects as you like to sum up the public properties.
function sumObjects(...$objects): object
{
$result = [];
foreach($objects as $object) {
foreach (get_object_vars($object) as $key => $value) {
isset($result[$key]) ? $result[$key] += $value : $result[$key] = $value;
}
}
return (object)$result;
}
$sumObject = sumObjects($objectA, $objectB);
stdClass Object
(
[a] => 3
[b] => 3
[d] => 3
)
There is no need to loop over both objects. Save the first object to the result object, then loop over the second object and add the related values between the current property and the result object. The null coalescing operator is used to add zero when there is no corresponding property in the result object.
Code: (Demo)
$result = $objectA;
foreach ($objectB as $prop => $value) {
$result->$prop = ($result->$prop ?? 0) + $value;
}
var_export($result);
If the properties between the two objects are guaranteed to be identical, then there is no need to coalesce with zero. Demo
$result = $objectA;
foreach ($objectB as $prop => $value) {
$result->$prop += $value;
}

php, sum two array values

I have two array
first array:
Array (
[01-1970] => 0.00
[03-2019] => 4350.00
[05-2019] => 150.00
[06-2019] => 50.00
)
second array:
Array (
[03-2019] => 0.00
[04-2019] => 0.00
[06-2019] => 34.83
)
My expected sum result is:
Array (
[01-1970] => 0.00
[03-2019] => 4350
[04-2019] => 0.00
[05-2019] => 150.00
[06-2019] => 84.83
)
How can achieve this?
You can use array_keys to get the unique from both of the array and then loop through keys to some them
$r = [];
$keys = array_keys($a1+$a2);
foreach($keys as $v){
$r[$v] = (empty($a1[$v]) ? 0 : $a1[$v]) + (empty($a2[$v]) ? 0 : $a2[$v]);
}
Working DEMO
Your best bet is to loop the arrays individually, and sum up the values into a resulting array as you go. We can create a new array that contains the two arrays them to shorten our code a bit (see how we define [$first, $second] as the first loop).
This removes any problems with mixed lengths, and keeps all the keys and values in the array intact.
$result = [];
// Loop over our two arrays, here called $first and $second
foreach ([$first, $second] as $a) {
// Loop over the values in each array
foreach ($a as $k=>$v) {
// If the index is new to the $result array, define it to be zero (to avoid undefined index notices)
if (!isset($result[$k]))
$result[$k] = 0;
// Sum up the value!
$result[$k] += $v;
}
}
print_r($result);
Live demo at https://3v4l.org/X4ijP
You can make use of a function I made:
<?php
function array_sum_multi($arrayOne, $arrayTwo)
{
# get rid of keys
$valuesOne = array_values($arrayOne);
$valuesTwo = array_values($arrayTwo);
//create return array
$output = [];
# loop that shizzle
for ($i = 0; $i < count($valuesOne); $i++)
{
$output[$i] = $valuesOne[$i] + (!empty($valuesTwo[$i]) ? $valuesTwo[$i] : 0);
}
return $output;
}
$result = array_sum_multi([0.00, 4350.00, 150.00, 50.00], [0.00, 0.00, 34.83]);
# then for your keys:
$result = array_combine(array_keys($yourFirstArray), $result);
echo '<pre>'. print_r($result, 1) .'</pre>';
$result = $first_array; // just copy array into result
// scan second array
foreach ($second_array as $k => $v) {
// if key already exists, then add, else just set
$result[$k] = isset($result[$k]) ? ($result[$k] + $v) : $v;
}
// done
print_r($result);
An easy way to implement it would be to loop through each array, and add it to a common array with the same key.
Looping through only one array would result in a lack of a few elements if the first array is smaller than the second one or if some element from the second array are not present in the first one.
So let's just loop through both of them and add it to sum.
$sum = [];
foreach($firstArray as $key => $value){
$sum[$key] = $value + (isset($sum[$key]) ? $sum[$key] : 0.0);
}
foreach($secondArray as $key => $value){
$sum[$key] = $value + (isset($sum[$key]) ? $sum[$key] : 0.0);
}
print_r($sum);
Try this simple method thank you,
$sum = [];
foreach($firstArray as $key => $value){
if(array_key_exists($key,$secondArray)){
$newArray = [$key=>$value+$secondArray[$key]];
$sum = array_merge($sum,$newArray);
}else{
$newArray = [$key=>$value];
$sum = array_merge($sum,$newArray);
}
}
//your final required result
var_dump($sum);
Try this,
$a1 = array (
'01-1970' => 0.00,
'03-2019' => 4350.00,
'05-2019' => 150.00,
'06-2019' => 50.00
);
$a2 = array (
'03-2019' => 0.00,
'04-2019' => 0.00,
'06-2019' => 34.83
);
$sums = array();
foreach (array_keys($a1 + $a2) as $key) {
$sums[$key] = #($a1[$key] + $a2[$key]);
}
echo "<pre>";
print_r($sums);
Here is some other solution you can use.
Cheer!
$sumArray = [];
foreach($firstArray as $key => $value) {
$sumArray[$key] = $value + ($secondArray[$key] ?? 0);
}

How to get a multidimensional array's name?

I'm trying to get the name of an array once I have found a specific value.
Specifically I'm looking to get the highest and lowest values within my array for a certain key, once I have those values I then need to get the name of the array holding those values.
My array looks like this -
Array
(
[123456] => Array
(
[value1] => 0.524
[value2] => 0.898
[value3] => -6.543
)
[246810] => Array
(
[value1] => 0.579
[value2] => 0.989
[value3] => -5.035
)
I have gotten the max value using this code -
max(array_column($statsArr, 'value1'));
This, correctly, gives me the value "0.579". I now need to get the value of the array holding this information so in this case I also want to get the value "246810". I don't know how to do this though, any help would be appreciated!
Iterate over your array with a simple foreach and save required key:
$max = 0;
$founded_key = false;
foreach ($array as $key => $value) {
if ($max < $value['value1']) {
$max = $value['value1'];
$founded_key = $key;
}
}
echo $founded_key, ' - ', $max;
For these kinds of problems I like using array_reduce. max is itself an array reduce operation which takes an array and returns a single value, PHP just offers it out of the box as convenience since it's a very common operation.
Here's an example code:
$array = array(
123456 => array(
'value1' => 0.524,
'value2' => 0.898,
'value3' => -6.543
),
246810 => array(
'value1' => 0.579,
'value2' => 0.989,
'value3' => -5.035
)
);
$maxKey = array_reduce(array_keys($array), function ($carry, $key) use ($array) {
if ($carry === null) {
return $key;
}
return $array[$key]['value1'] > $array[$carry]['value1'] ? $key : $carry;
}, null);
$maxValue = $array[$maxKey]['value1'];
Working example: http://sandbox.onlinephpfunctions.com/code/ecd400ffec91a6436c2fb5ee0410658e22772d4b
function getMax($array, $field) {
$maxValue = null;
$maxKey = null;
foreach($array as $key => $content) {
if (is_null($maxValue) || $content[$field] > $maxValue) {
$maxValue = $content[$field];
$maxKey = $key;
}
}
return [$maxValue, $maxKey];
}
You can search for the maximum value in the array_column.
I first prepare the array_column with correct keys by combining it, then find the max like you do.
Then we can array_search the value.
$value1 = array_combine(array_keys($statsArr), array_column($statsArr, 'value1'));
$max = max($value1);
echo $max . PHP_EOL;
$array = $statsArr[array_search($max, $value1)];
var_dump($array);
https://3v4l.org/Q9gOX
Alternatively you can array_values the $statsArr to make it 0 indexed just like the array_column.
$value1 = array_column($statsArr, 'value1');
$max = max($value1);
echo $max . PHP_EOL;
$array = array_values($statsArr)[array_search($max, $value1)];
var_dump($array);

Pad short input arrays with their last element value to ensure equal lengths and transpose arrays into one array

I have the following Arrays:
$front = array("front_first","front_second");
$inside = array("inside_first", "inside_second", "inside_third");
$back = array("back_first", "back_second", "back_third","back_fourth");
what I need to do is combine it so that an output would look like this for the above situation. The output order is always to put them in order back, front, inside:
$final = array(
"back_first",
"front_first",
"inside_first",
"back_second",
"front_second",
"inside_second",
"back_third",
"front_second",
"inside_third",
"back_fourth",
"front_second",
"inside_third"
);
So basically it looks at the three arrays, and whichever array has less values it will reuse the last value multiple times until it loops through the remaining keys in the longer arrays.
Is there a way to do this?
$front = array("front_first","front_second");
$inside = array("inside_first", "inside_second", "inside_third");
$back = array("back_first", "back_second", "back_third","back_fourth");
function foo() {
$args = func_get_args();
$max = max(array_map('sizeof', $args)); // credits to hakre ;)
$result = array();
for ($i = 0; $i < $max; $i += 1) {
foreach ($args as $arg) {
$result[] = isset($arg[$i]) ? $arg[$i] : end($arg);
}
}
return $result;
}
$final = foo($back, $front, $inside);
print_r($final);
demo: http://codepad.viper-7.com/RFmGYW
Demo
http://codepad.viper-7.com/xpwGha
PHP
$front = array("front_first", "front_second");
$inside = array("inside_first", "inside_second", "inside_third");
$back = array("back_first", "back_second", "back_third", "back_fourth");
$combined = array_map("callback", $back, $front, $inside);
$lastf = "";
$lasti = "";
$lastb = "";
function callback($arrb, $arrf, $arri) {
global $lastf, $lasti, $lastb;
$lastf = isset($arrf) ? $arrf : $lastf;
$lasti = isset($arri) ? $arri : $lasti;
$lastb = isset($arrb) ? $arrb : $lastb;
return array($lastb, $lastf, $lasti);
}
$final = array();
foreach ($combined as $k => $v) {
$final = array_merge($final, $v);
}
print_r($final);
Output
Array
(
[0] => back_first
[1] => front_first
[2] => inside_first
[3] => back_second
[4] => front_second
[5] => inside_second
[6] => back_third
[7] => front_second
[8] => inside_third
[9] => back_fourth
[10] => front_second
[11] => inside_third
)
Spreading the column data from multiple arrays with array_map() is an easy/convenient way to tranpose data. It will pass a full array of elements from the input arrays and maintain value position by assigning null values where elements were missing.
Within the custom callback, declare a static cache of the previously transposed row. Iterate the new transposed row of data and replace any null values with the previous rows respective element.
After transposing the data, call array_merge(...$the_transposed_data) to flatten the results.
Code: (Demo)
$front = ["front_first", "front_second"];
$inside = ["inside_first", "inside_second", "inside_third"];
$back = ["back_first", "back_second", "back_third", "back_fourth"];
var_export(
array_merge(
...array_map(
function(...$cols) {
static $lastSet;
foreach ($cols as $i => &$v) {
$v ??= $lastSet[$i];
}
$lastSet = $cols;
return $cols;
},
$back,
$front,
$inside
)
)
);
Output:
array (
0 => 'back_first',
1 => 'front_first',
2 => 'inside_first',
3 => 'back_second',
4 => 'front_second',
5 => 'inside_second',
6 => 'back_third',
7 => 'front_second',
8 => 'inside_third',
9 => 'back_fourth',
10 => 'front_second',
11 => 'inside_third',
)

PHP: Count the appearance of particular value in array

I am wondering if I could explain this.
I have a multidimensional array , I would like to get the count of particular value appearing in that array
Below I am showing the snippet of array . I am just checking with the profile_type .
So I am trying to display the count of profile_type in the array
EDIT
Sorry I've forgot mention something, not something its the main thing , I need the count of profile_type==p
Array
(
[0] => Array
(
[Driver] => Array
(
[id] => 4
[profile_type] => p
[birthyear] => 1978
[is_elite] => 0
)
)
[1] => Array
(
[Driver] => Array
(
[id] => 4
[profile_type] => d
[birthyear] => 1972
[is_elite] => 1
)
)
)
Easy solution with RecursiveArrayIterator, so you don't have to care about the dimensions:
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
$counter = 0
foreach ($iterator as $key => $value) {
if ($key == 'profile_type' && $value == 'p') {
$counter++;
}
}
echo $counter;
Something like this might work...
$counts = array();
foreach ($array as $key=>$val) {
foreach ($innerArray as $driver=>$arr) {
$counts[] = $arr['profile_type'];
}
}
$solution = array_count_values($counts);
I'd do something like:
$profile = array();
foreach($array as $elem) {
if (isset($elem['Driver']['profile_type'])) {
$profile[$elem['Driver']['profile_type']]++;
} else {
$profile[$elem['Driver']['profile_type']] = 1;
}
}
print_r($profile);
You may also use array_walk($array,"test") and define a function "test" that checks each item of the array for 'type' and calls recursively array_walk($arrayElement,"test") for items of type 'array' , else checks for the condition. If condition satisfies, increment a count.
Hi You can get count of profuke_type==p from a multi dimensiona array
$arr = array();
$arr[0]['Driver']['id'] = 4;
$arr[0]['Driver']['profile_type'] = 'p';
$arr[0]['Driver']['birthyear'] = 1978;
$arr[0]['Driver']['is_elite'] = 0;
$arr[1]['Driver']['id'] = 4;
$arr[1]['Driver']['profile_type'] = 'd';
$arr[1]['Driver']['birthyear'] = 1972;
$arr[1]['Driver']['is_elite'] = 1;
$arr[2]['profile_type'] = 'p';
$result = 0;
get_count($arr, 'profile_type', 'd' , $result);
echo $result;
function get_count($array, $key, $value , &$result){
if(!is_array($array)){
return;
}
if($array[$key] == $value){
$result++;
}
foreach($array AS $arr){
get_count($arr, $key, $value , $result);
}
}
try this..
thanks

Categories