PHP indexed array to nested associative array - php

I need to convert simple array to nested array according to specific rules. I've achived it but I'm looking for better solution.
SIMPLE:
array(4) {
[0]=>
array(2) {
["id"]=>
string(2) "11"
["type"]=>
int(3)
}
[1]=>
array(2) {
["id"]=>
string(2) "10"
["type"]=>
int(2)
}
[2]=>
array(2) {
["id"]=>
string(1) "1"
["type"]=>
int(1)
}
[3]=>
array(2) {
["id"]=>
string(1) "0"
["type"]=>
int(1)
}
}
EXPECTED EFFECT:
array(1) {
[0]=>
array(2) {
["type"]=>
int(1)
["child"]=>
array(1) {
[1]=>
array(2) {
["type"]=>
int(1)
["child"]=>
array(1) {
[10]=>
array(2) {
["type"]=>
int(2)
["child"]=>
array(1) {
[11]=>
array(2) {
["type"]=>
int(3)
["child"]=>
array(0) {
}
}
}
}
}
}
}
}
}
MY SOLUTION (not very satisfying):
$nestedArray = [];
foreach ($simpleArray as $item)
{
if (!empty($nestedArray))
{
$array = $nestedArray;
reset($array);
$firstKey = key($array);
}
$nestedArray[$item['id']]['child'] = $nestedArray;
$nestedArray[$item['id']]['type'] = $item['type'];
if (!empty($firstKey))
{
unset($nestedArray[$firstKey]);
}
}
As I said, I'm looking for more elegant way to achieve that. Rule are very simply: every next item is child of previous.

You could use recursion:
function nest($arr) {
return count($arr) ? ["type" => array_pop($arr)["type"], "child" => nest($arr)] : [];
}
With your example input, it would look like this:
$simpleArray = [
["id" => "11", "type" => 3],
["id" => "10", "type" => 2],
["id" => "1", "type" => 1],
["id" => "0", "type" => 1]
];
function nest($arr) {
return count($arr) ? ["type" => array_pop($arr)["type"], "child" => nest($arr)] : [];
}
$nested = nest($simpleArray));
$nested will have the following value:
[
"type" => 1,
"child" => [
"type" => 1,
"child" => [
"type" => 2,
"child" => [
"type" => 3,
"child" => []
]
]
]
]

Related

Convert PHP associative array to new array but only with specific keys?

I have data array on this way:
array(3) {
[0]=>
array(2) {
["name"]=>
string(13) "Register Page"
["id"]=>
string(1) "5"
}
[1]=>
array(2) {
["name"]=>
string(10) "Login Page"
["id"]=>
string(1) "6"
}
[2]=>
NULL
}
My goal is to get from the array above something like this:
array(5,6,null);
Thanks!
Look at the PHP function array_map
$array = [
["name" => "Register Page", "id" => 5 ],
["name" => "Login Page", "id" => 6 ],
NULL
];
$ids = array_map( function($rec) { return $rec['id'] ?? null; }, $array);
Assuming your data is in $a:
foreach ( $a as $a2 ) {
if ( is_array($a2) && $a2['id'] ) {
$r[] = $a2['id']; // or (int) $a2['id'] if you want to cast it to an int
} else {
$r[] = NULL;
}
}

Restructure array data by chunking, transposing, and merging

I have array mentioned below, I will have value always multiple of 3.
$xyz = [
["name" => "abc"],
["name" => "snds"],
["name" => ""),
["number"=> "452"],
["number" => "845120"],
["number" => "84514513200"],
["email" => "ddddf"],
["email" => "dkskns"],
["email" => "kjnksdnkds"]
];
but this is not the proper format for me to perform further operations, so I want this array like mentioned below.
$abc = [
[
"name" => "abc",
"number" => '452',
"email" => "ddddf"
],
[
"name" => "snds",
"number" => "845120",
"email" => "dkskns"
],
[
"name" => "",
"number" => "84514513200",
"email" => "kjnksdnkds"
]
];
note: the array length is dynamic but it will always be multiple of 3
One possibility could be to use the modulo % operator.
In the foreach the value is an array and you could use array_keys to get the key and reset to get the value of the first array element.
$result = [];
$count = 0;
foreach ($xyz as $value) {
if ($count%3 === 0) {
$count = 0;
}
$result[$count][array_keys($value)[0]] = reset($value);
$count++;
}
Demo
That will give you:
array(3) {
[0]=>
array(3) {
["name"]=>
string(3) "abc"
["number"]=>
string(3) "452"
["email"]=>
string(5) "ddddf"
}
[1]=>
array(3) {
["name"]=>
string(4) "snds"
["number"]=>
string(6) "845120"
["email"]=>
string(6) "dkskns"
}
[2]=>
array(3) {
["name"]=>
string(0) ""
["number"]=>
string(11) "84514513200"
["email"]=>
string(10) "kjnksdnkds"
}
}
This will do:
$result = array_map('array_merge', ...array_chunk($xyz, count($xyz) / 3));

How to remove items that exist in the array from object?

This is how my array looks like:
array(3) {
[0]=>
string(3) "600"
[1]=>
string(3) "601"
[2]=>
string(3) "603"
}
This is how my object looks like:
array(7) {
[0]=>
object(stdClass)#688 (6) {
["id"]=>
string(3) "601"
["name"]=>
string(10) "test8opkpo"
["avatar"]=>
string(85) "http://avatars/user/medium.png"
["url"]=>
string(86) "/index.php"
["isOnline"]=>
int(0)
["lastseen"]=>
string(11) "2 weeks ago"
}
[1]=>
object(stdClass)#689 (6) {
["id"]=>
string(3) "604"
["name"]=>
string(6) "nopita"
["avatar"]=>
string(85) "http://avatars/user/medium.png"
["url"]=>
string(82) "/index.php"
["isOnline"]=>
int(0)
["lastseen"]=>
string(10) "1 week ago"
}
[2]=>
object(stdClass)#690 (6) {
["id"]=>
string(3) "603"
["name"]=>
string(6) "test_b"
["avatar"]=>
string(85) "http://avatars/user/medium.png"
["url"]=>
string(82) "/index.php"
["isOnline"]=>
int(0)
["lastseen"]=>
string(11) "6 hours ago"
}
Now I want to remove from the object, each item's id that matches the value inside the array.
So final output of the object should not contain id's that present in the array given. How to do that?
I tried using array_diff_key and unset to no avail.
$contactArray[$i] represent each id in the object
if (in_array($contactArray[$i], $array)) {
$a = array_diff_key($results->contacts, [$i => $contactArray[$i]]);
}
I created my own set of examples to simulate what you want to happen on your array:
$x = array('600','601', '603');
$y = array(
array("id" => "600",
"name" => "test",
"avatar" => "image"
),
array("id" => "601",
"name" => "test1",
"avatar" => "image1"
),
array("id" => "602",
"name" => "test2",
"avatar" => "image2"
),
array("id" => "603",
"name" => "test3",
"avatar" => "image3"
),
array("id" => "604",
"name" => "test4",
"avatar" => "image4"
)
);
echo '<pre>';
var_dump($y);
echo '</pre>';
$new_arr_ = array();
for($i = 0, $ctr = count($y); $i < $ctr; $i++) {
if(!in_array($y[$i]["id"], $x)) {
$new_arr_[] = array($y[$i]["id"], $y[$i]["name"], $y[$i]["avatar"]);
}
}
echo '<pre>';
var_dump($new_arr_);
echo '</pre>';
Hope it helps.
If I understand you correctly the following should work:
$contactArray = array_filter($contactArray, function ($v) use ($array) {
return !in_array(isset($v->id)?$v->id:null, $array);
});

PHP references in uasort function

I have
$products = array(
"product1" => [
"a" => ["total" => 1],
"b" => ["total" => 3],
"c" => ["total" => 2],
],
"product2" => [
"d" => ["total" => 3],
"f" => ["total" => 2],
"e" => ["total" => 1],
],
"product3" => [
"g" => ["total" => 3]
],
);
theses are my products and my stocks for each warehouses (warehouse a has 1 item of product1...)
I want to sort each warehouse by stock for each products.
I've done that :
foreach ($products as &$stocks) {
uasort($stocks, function($elmt1, $elmt2) {
return $elmt2["total"] - $elmt1["total"];
});
}
where I print my new array :
array(3) {
["product1"]=>
array(3) {
["b"]=>
array(1) {
["total"]=>
int(3)
}
["c"]=>
array(1) {
["total"]=>
int(2)
}
["a"]=>
array(1) {
["total"]=>
int(1)
}
}
["product2"]=>
array(3) {
["d"]=>
array(1) {
["total"]=>
int(3)
}
["f"]=>
array(1) {
["total"]=>
int(2)
}
["e"]=>
array(1) {
["total"]=>
int(1)
}
}
["product3"]=>
&array(1) {
["g"]=>
array(1) {
["total"]=>
int(3)
}
}
}
It did my job but when I get a closer look I can see the "&" char in only one of the arrays.
Why ?
Due to the fact that $item - a reference to the last element of the array.
You can do this trick:
$array = ['a', 'b', 'c'];
foreach ($array as &$item) {
}
foreach ($array as $item) {
$item = 1;
}
var_dump($array);
Output:
array(3) {
[0]=>
string(1) "a"
[1]=>
string(1) "b"
[2]=>
&int(1)
}
It's not terrible, as long as you do not start to use $item.
It is better to make a job with reference in different function
$array = ['a', 'b', 'c'];
$test = function () use (&$array) {
foreach ($array as &$item) {
}
};
$test();
var_dump($array);
Output:
array(3) {
[0]=>
string(1) "a"
[1]=>
string(1) "b"
[2]=>
string(1) "c"
}
Or try this:
$products = array(
"product1" => [
"a" => ["total" => 1],
"b" => ["total" => 3],
"c" => ["total" => 2],
],
"product2" => [
"d" => ["total" => 3],
"f" => ["total" => 2],
"e" => ["total" => 1],
],
"product3" => [
"g" => ["total" => 3]
],
);
foreach ($products as $key=>$stocks) {
uasort($products[$key], function($elmt1, $elmt2) {
return $elmt2["total"] - $elmt1["total"];
});
}
var_dump($products);
Output:
array(3) {
["product1"]=>
array(3) {
["b"]=>
array(1) {
["total"]=>
int(3)
}
["c"]=>
array(1) {
["total"]=>
int(2)
}
["a"]=>
array(1) {
["total"]=>
int(1)
}
}
["product2"]=>
array(3) {
["d"]=>
array(1) {
["total"]=>
int(3)
}
["f"]=>
array(1) {
["total"]=>
int(2)
}
["e"]=>
array(1) {
["total"]=>
int(1)
}
}
["product3"]=>
array(1) {
["g"]=>
array(1) {
["total"]=>
int(3)
}
}
}

sum values with given key in php? [duplicate]

This question already has answers here:
How to GROUP BY and SUM PHP Array? [duplicate]
(2 answers)
Closed 5 months ago.
given this array:
array(40) {
[0]=>
array(10) {
["item"]=>
string(5) "AABBCC"
["quants"]=>
string(1) "1"
}
[1]=>
array(10) {
["item"]=>
string(5) "AABBCC"
["quants"]=>
string(1) "1"
}
[2]=>
array(10) {
["item"]=>
string(5) "SLF02"
["quants"]=>
string(1) "1"
}
[3]=>
array(10) {
["item"]=>
string(5) "SLF02"
["quants"]=>
string(1) "3"
}
}
how without using a foreach do I end up with this output:
array(40) {
[0]=>
array(10) {
["item"]=>
string(5) "AABBCC"
["quants"]=>
string(1) "2"
}
[1]=>
array(10) {
["item"]=>
string(5) "SLF02"
["quants"]=>
string(1) "3"
}
}
are there any array_sum functions to do this with a multidimensional array like this in php?
This is a bad idea, but seemed like a fun challenge to do without a foreach:
$arr =
[
[
"item" =>"AABBCC",
"quants" => "1",
],
[
"item" => "AABBCC",
"quants" => "1",
],
[
"item" => "SLF02",
"quants" => "1",
],
[
"item" => "SLF02",
"quants" => "3",
]
];
$arr = array_values(call_user_func_array("array_merge", array_map(function($i) use ($arr) {
return [$i["item"] => ["item" => $i["item"], "quants" => array_reduce(
array_filter($arr, function($j) use ($i) {
return $j["item"] == $i["item"];
}), function($carry, $item) {
return $carry + $item["quants"];
})
]];
}, $arr)));
var_dump($arr);
/*
array(2) {
[0]=>
array(2) {
["item"]=>
string(6) "AABBCC"
["quants"]=>
int(2)
}
[1]=>
array(2) {
["item"]=>
string(5) "SLF02"
["quants"]=>
int(4)
}
}
*/
Here's my approach:
<?php
$array = array(
array('item'=>'AABBCC','quants'=>1),
array('item'=>'AABBCC','quants'=>1),
array('item'=>'SLF02','quants'=>1),
array('item'=>'SLF02','quants'=>3),
);
$summed_array = array();
foreach($array as $row){
$key = $row['item'];
if(!isset($summed_array[$key])){
$summed_array[$key] = array(
'item' => $row['item'],
'quants' => 0
);
}
$summed_array[$key]['quants'] += $row['quants'];
}
// turn the array back to a 0 based array
$summed_array = array_values($summed_array);
echo '<pre>',print_r($summed_array),'</pre>';

Categories