PHP - add values to already existing array - php

I have a already defined array, containing values just like the one below:
$arr = ['a','b','c'];
How could one add the following using PHP?
$arr = [
'a' => 10,
'b' => 5,
'c' => 21
]
I have tried:
$arr['a'] = 10 but it throws the error: Undefined index: a
I am surely that I do a stupid mistake.. could someone open my eyes?
Full code below:
$finishes = []; //define array to hold finish types
foreach ($projectstages as $stage) {
if ($stage->finish_type) {
if(!in_array($stage->finish_type, $finishes)){
array_push($finishes, $stage->finish_type);
}
}
}
foreach ($projectunits as $unit) {
$data[$i] = [
'id' => $unit->id,
'project_name' => $unit->project_name,
'block_title' => $unit->block_title,
'unit' => $unit->unit,
'core' => $unit->core,
'floor' => $unit->floor,
'unit_type' => $unit->unit_type,
'tenure_type' => $unit->tenure_type,
'floors' => $unit->unit_floors,
'weelchair' => $unit->weelchair,
'dual_aspect' => $unit->dual_aspect
];
$st = array();
$bs = '';
foreach ($projectstages as $stage) {
$projectmeasure = ProjectMeasure::select('measure')
->where('project_id',$this->projectId)
->where('build_stage_id', $stage->id)
->where('unit_id', $unit->id)
->where('block_id', $unit->block_id)
->where('build_stage_type_id', $stage->build_stage_type_id)
->first();
$st += [
'BST-'.$stage->build_stage_type_id => ($projectmeasure ? $projectmeasure->measure : '0')
];
if (($stage->is_square_meter == 0) && ($stage->is_draft == 0)) {
$height = ($stage->height_override == 0 ? $unit->gross_floor_height : $stage->height_override); //08.14.20: override default height if build stage type has it's own custom height
$st += [
'BST-sqm-'.$stage->build_stage_type_id => ($projectmeasure ? $projectmeasure->measure * $height: '0')
];
if ($stage->finish_type) {
$finishes[$stage->finish_type] += ($projectmeasure ? $projectmeasure->measure * $height: '0') * ($stage->both_side ? 2 : 1); //error is thrown at this line
}
} else {
if ($stage->finish_type) {
$finishes[$stage->finish_type] += ($projectmeasure ? $projectmeasure->measure : '0');
}
}
}
$data[$i] = array_merge($data[$i], $st);
$data[$i] = array_merge($data[$i], $finishes[$stage->finish_type]);
$i++;
}
The above code is used as is and the array $finishes is the one from the first example, called $arr

You're using += in your real code instead of =. That tries to do maths to add to an existing value, whereas = can just assign a new index with that value if it doesn't exist.
+= can't do maths to add a number to nothing. You need to check first if the index exists yet. If it doesn't exist, then assign it with an initial value. If it already exists with a value, then you can add the new value to the existing value.

If you want to convert the array of strings to a collection of keys (elements) and values (integers), you can try the following:
$arr = ['a','b','c'];
$newVals = [10, 5, 21];
function convertArr($arr, $newVals){
if(count($arr) == count($newVals)){
$len = count($arr);
for($i = 0; $i < $len; $i++){
$temp = $arr[$i];
$arr[$temp] = $newVals[$i];
unset($arr[$i]);
}
}
return $arr;
}
print_r(convertArr($arr, $newVals));
Output:
Array ( [a] => 10 [b] => 5 [c] => 21 )

Related

Multidimensional Array Search by Multiple Keys given as Variable?

I have a multidimensional array which has keys and key has values or have another array with keys and values so I want to search by keys but in input like 230 is user input
and it will go to 3 then 4 then 1 if result is a value but not an array it must print the value like
input = 230 result should be = "3-4-1"
so I need to str_split the number and search it 1 by 1 if first number is array then look for second kinda
edit1 = I found the way to split the key
//edit1
$keys = "021";
$keysSplit =str_split($keys, strlen($keys)/strlen($keys));
echo $keys[0];
//edit 1 ends
$arr = [0 => [0=>"1-1", 1 => "1-2" , 2=>"1-3", 3=>[0=>"1-4-1", 1 => "1-4-2" , 2=>"1-4-3"]],
1 => [0=>"2-1", 1 => "2-2" , 2=>"2-3"],
2 => [0=>"3-1", 1 => "3-2" , 2=>"3-3", 3=>[0 =>"3-4-1" , 1=> "3-4-2"]],
];
$keys = "021";
function searchByKey($array , $keys){
$result = [];
$keys = "021";
$keys =str_split($keys, strlen($keys)/strlen($keys));
$key1 = $keys[0];
$key2 = $keys [1];
$key3 = $keys [2];
foreach ($array as $key1 => $value){
if (is_array($value)){
$key1 = null;
$key1 = $key2;
$key2 = $key3;
return searchByKey($value , $key1);
}
else {
$result=$value;
echo $result;
}
}
}
$arr = searchByKey($arr, $keys);
The function only works as key and value given and it will print every key and value on the key it asked first so its not the thing I wanted to do could anyone help and explain?
Answer given by #Anggara I made it in to function ;
$input = "11";
function searchByNumber($array, $input){
$result = $array;
for ($i = 0; $i < strlen($input); $i++) {
if (is_array($result)) {
$result = $result[$input[$i]];
} else {
$result = "Does not exists";
break;
}
}
echo $result;
}
$arr = searchByNumber($arr, $input);
You can access char in string like accessing an array. For example:
$input = "230";
// $input[0] is "2"
// $input[1] is "3"
// $input[2] is "0"
So my approach is to loop for each character in input key, and look for corresponding value in $arr. Each iteration will set found array element into variable $result. If the searched key does not exist (ex: "021"), print error message.
<?php
$arr = [
0 => [
0 => "1-1",
1 => "1-2",
2 => "1-3",
3 => [
0 => "1-4-1",
1 => "1-4-2",
2 => "1-4-3"
]
],
1 => [
0 => "2-1",
1 => "2-2",
2 => "2-3"
],
2 => [
0 => "3-1",
1 => "3-2",
2 => "3-3",
3 => [
0 => "3-4-1",
1 => "3-4-2"
]
],
];
$input = "230";
$result = $arr;
for ($i = 0; $i < strlen($input); $i++) {
if (is_array($result)) {
$result = $result[$input[$i]];
} else {
$result = 'Can not traverse path';
break;
}
}
echo $result;
After splitting the keys
for($i=0;$i<strlen($keys);$i++){
$arr = $arr[$keys[$i]];
}
if(is_array($arr)){
echo json_encode($arr);
}else{
echo $arr;
}
You need a loop, which will go through the keys one by one and assigning into the array.

Check data in array for null values

I want to check data in array to see if there are null values. If there are, I'd like to display an alert.
Example:
$data = array(1 => 'AKB48', 2 => '', 3 => 'JKT48');
The Array of index 1 ($data[1]) is null, and I want it to display "WARNING, data in array is null"
if data in array does not have empty/null values then don't show an alert:
$data = array(1 => 'AKB48', 2 => 'HKT48', 3 => 'JKT48');
(the above array will no trigger an alert)
How can I achieve this solution?
something like this?
$data = array(1 => 'AKB48', 2 => '', 3 => 'JKT48');
foreach($data as $val) {
if($val == '') {
echo "alert, array consist of empty value";
}
}
$data = array(1 => 'AKB48', 2 => '', 3 => 'JKT48');
foreach($data as $v)
{
if(empty($v))
{
echo "Array contains null value";
break;
}
}
Something like this?
isDefined will check if the value is a valid non-empty String.
function isDefined($var) {
return isset($var) && !is_null($var) && !empty($var);
}
$data = array(
array('AKB48', 'HKT48', NULL),
array('AKB49', '', 'JKT49'),
array('AKB50', 'HKT50', 'JKT50')
);
for ($i = 0; $i < count($data); $i++) {
foreach ($data[$i] as $col) {
if (!isDefined($col)) {
echo "<<<Attention: Array #$i contains an empty value!>>> ";
}
}
}
Running example of code above.

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',
)

Convert multidimensional array to nested set array

im having a little problem i need some help with.
Im trying to convert a multidimensional array into a flatten array with nested set values right and left like so:
$array = {
'id' => 1
'name' => 'john'
'childs' => array(
array(
'id' => 1
'name' => 'jane'
)
)
}
to
$array = {
array(
'id' => 1,
'name' => 'john'
'left' => '1'
'right' => '4'
),
array(
'id' => 1,
'name' => 'jane'
'left' => '2'
'right' => '3'
)
}
Any help is appreciated!
I asked a very similar question and got a result, so thought I'd send it on for you. I realise this is quite an old topic, but still worth getting an answer. I've included my data, but would be easily adapted for yours.
$JSON = '[{"id":1,"children":[{"id":2,"children":[{"id":3},{"id":4}]},{"id":5}]}]';
$cleanJSON = json_decode($JSON,true);
$a_newTree = array();
function recurseTree($structure,$previousLeft)
{
global $a_newTree; // Get global Variable to store results in.
$indexed = array(); // Bucket of results.
$indexed['id'] = $structure['id']; // Set ID
$indexed['left'] = $previousLeft + 1; // Set Left
$lastRight = $indexed['left'];
$i_count = 0;
if ($structure['children'])
{
foreach ($structure['children'] as $a_child)
{
$lastRight = recurseTree($structure['children'][$i_count],$lastRight);
$i_count++;
}
}
$indexed['right'] = $lastRight + 1; // Set Right
array_push($a_newTree,$indexed); // Push onto stack
return $indexed['right'];
}
recurseTree($cleanJSON[0],0);
print_r($a_newTree);
function restructRecursive($array, $left = 1) {
if (isset($array['childs'])) {
$result = array();
foreach ($array['childs'] as $child) {
$result = array_merge($result, restructRecursive($child, $left+1));
}
unset($array['childs']);
}
$array['left'] = $left;
return array_merge(array($array), $result);
}
$newStruct = restructRecursive($oldStruct);
For anyone coming here and looking for a solution, loneTraceur's solution works fine. However, I needed one in OOP, so here is my version of it.
<?php
class NestedSet
{
protected $tree = [];
public function deconstruct($tree, $left = 0)
{
$this->flattenTree($tree, $left);
return $this->tree;
}
protected function flattenTree($tree, $left)
{
$indexed = [];
$indexed['id'] = $tree['id'];
$indexed['_lft'] = $left + 1;
$right = $indexed['_lft'];
if (isset($tree['children']) && count($tree['children'])) {
foreach ($tree['children'] as $child) {
$right = $this->flattenTree($child, $right);
}
}
$indexed['_rgt'] = $right + 1;
$this->tree[] = $indexed;
return $indexed['_rgt'];
}
}
You would run it like this:
$NestedSet = new NestedSet;
$flat = $NestedSet->deconstruct($tree):
This code is based on the other answer.

Find maximum value in associative array

I have a associative array:
$users[0] = array('name' => 'Jim', 'depth' => '1', 'bk_id' => '9');
$users[1] = array('name' => 'Jill', 'depth' => '3', 'bk_id' => '10');
$users[2] = array('name' => 'Jack', 'depth' => '7', 'bk_id' => '17');
I would like to know a way of finding the array index with the maximum or greatest depth value?
Any suggestion is most appreciated.
Just iterate and look at the maximum value:
var max = 0, maxIndex = -1;
for(var i=0;i<users.length;i++) {
if(parseInt(users[i].depth,10) > max) {
max = users[i].depth;
maxIndex = i;
}
}
console.log("Your maximum depth is %d at index %d", max, maxIndex);
From PHP:
$index = 0;
$max = 0;
for ($i = 0; $i < count($users); $i++) {
if ($users[$i]['depth'] > $max) {
$max = $users[$i]['depth'];
$index = $i;
}
}
echo $users[$index]['name'] . ' has the greatest depth.';
Since the question is unclear, here's how to find it with PHP.
foreach ($users as $index => $user) {
if (!isset($maxdepth)) {
$maxdepth = $user['depth'];
$maxindex = $index;
}
else {
if ($user['depth']) > $maxdepth) {
$maxindex = $index;
$maxdepth = $user['depth'];
}
}
echo "Index: $maxindex";
You can either iterate over all the key-value pairs looking at the depth value each time, or sort the $users array using a custom sort function like sort_func(){ return a.depth - b.depth}
Using native sort function?
function getDeepestItem(arr)
{
arr.sort(function(a,b){return a['depth'] < b['depth'];});
return arr[0]
}

Categories