Creating, Accessing and understanding multidimensional arrays in php - php

I have implemented the following small example:
$nodeList;
for($i = 0; $i < 10;$i++) {
$nodeList[$i] = $i;
for($j = 0; $j < 3;$j++) {
$nodeList[$i][$j] = $j;
}
}
foreach($nodeList[0] as $nodeEl) {
print "NodeEl: ".$nodeEl." | ";
}
print nl2br("\n\r");
$testList = array
(
array(1,2,3),
array(4,5,6),
array(7,8,9),
array(10,11,12),
);
foreach($testList[0] as $testEl) {
print "TestEl: ".$testEl." | ";
}
Where the output for $nodeList is null (var_dump / print_r too) and the output for $testList is TestEl: 1 | TestEl: 2 | TestEl: 3, as expected.
In my understanding those two solutions should create roughly the same output - but instead there is no output for the first one at all. Because the second dimension of the array is not even created.
Reading up on http://php.net/manual/de/language.types.array.php creates the strong feeling that the [] operator is only for dereferencing / accessing of the array, but then again the docs provide a sample where they assign a value to a certain key the same way I do $arr["x"] = 42.
What is the difference between these two ways of array access?
How can I achieve filling a n-dimensional array in a way similar to the way I try to fill $nodeList?

You should make sure to have error reporting turned on, because warnings are generated for your code:
E_WARNING : type 2 -- Cannot use a scalar value as an array -- at line 7
This concerns the following statement:
$nodeList[$i] = $i;
If you want to create a 2D array, there is no meaning in assigning a number on the first level. Instead you want $nodeList[$i] to be an array. PHP does that implicitely (creating the array) when you access it with brackets [...], so you can just leave out the offending statement, and do:
for($i = 0; $i < 10;$i++) {
for($j = 0; $j < 3;$j++) {
$nodeList[$i][$j] = $j;
}
}
You can even leave out the $j in the last bracket pair, which means PHP will just add to the array using the next available numerical index:
for($i = 0; $i < 10;$i++) {
for($j = 0; $j < 3;$j++) {
$nodeList[$i][] = $j;
}
}
Adding a value at every level
If you really need to store $i at the first level of the 2D array, then consider using a more complex structure where each element is an associative array with two keys: one for the value and another for the nested array:
for($i = 0; $i < 10; $i++) {
$nodeList[$i] = array(
"value" => $i,
"children" => array()
);
for($j = 0; $j < 3;$j++) {
$nodeList[$i]["children"][] = array(
"value" => "$i.$j" // just example of value, could be just $j
);
}
}
$nodeList will be like this then:
array (
array (
'value' => 0,
'children' => array (
array ('value' => '0.0'),
array ('value' => '0.1'),
array ('value' => '0.2'),
),
),
array (
'value' => 1,
'children' => array (
array ('value' => '1.0'),
array ('value' => '1.1'),
array ('value' => '1.2'),
),
),
//...etc
);

You should write
<?php
$nodeList;
for($i = 0; $i < 10;$i++) {
for($j = 0; $j < 3;$j++) {
$nodeList[$i][$j] = $j;
}
}
foreach($nodeList[0] as $nodeEl) {
print "NodeEl: ".$nodeEl." | ";
}

You need to declare $nodeList as array like
$nodeList=array();
and for 2D array
$nodeList= array(array());

Related

Set array value in a for loop php

Apologies for the dumb question, I just can't seem to understand what's exactly going on. I have a JS function which I transformed into PHP and in the JS everything is working as desired.
The problem with the PHP one is here I believe:
I have last element of and array which I get by
$lastPeriod = end($periods);
while being in a for loop.
Next I set the value of $lastPeriod['closeTime'] to equal a number. If I dd($lastPeriod) after changing it's value it is updated, however if I dd(); at the end it is not. Maybe there is a conflict with how I remove the next element so the end is not working correctly?
for ( $i = 0; $i < sizeof($dailyHours); $i++ )
{
$periods = $dailyHours[$i]['periods'];
for ($j = 0; $j < sizeof($periods); $j++)
{
$lastPeriod = end($periods);
if ($lastPeriod['closeTime'] === '00:00'
&& $dailyHours[$i + 1]['periods'][0]['openTime'] === '00:00'
&& $dailyHours[$i + 1]['periods'][0]['closeTime'] !== '00:00')
{
if (Carbon::parse($dailyHours[$i + 1]['periods'][0]['closeTime'])->isBefore(Carbon::createFromTimeString('11:59')))
{
$lastPeriod['closeTime'] = $dailyHours[$i + 1]['periods'][0]['closeTime'];
array_splice($dailyHours[$i + 1]['periods'], 0, 1);
if (sizeof($dailyHours[$i + 1]['periods']) < 1)
{
$dailyHours[$i + 1]['isOpen'] = 0;
}
}
}
}
}
}
The problem is that you are editing a copy of the array.
Let's look at this example:
<?php
$myPets = [
[
'animal' => 'cat',
'name' => 'john'
],
];
$pet = $myPets[0];
$pet['name'] = 'NewName';
var_dump($myPets);
When I run this program the name of my pet should be 'NewName' right?
array(1) {
[0]=>
array(2) {
["animal"]=>
string(3) "cat"
["name"]=>
string(4) "john"
}
}
Well, as you can see the name hasn't changed.
This is because when we do $pet = $myPets[0] PHP will make a copy of the $myPets[0] array.
To fix this you can take the reference of that array by doing:
$pet = &$myPets[0].
There are a few issues in the code:
In a loop you have this code:
$lastPeriod = end($periods);
Then later on you have:
$lastPeriod['closeTime'] = $dailyHours[$i + 1]['periods'][0]['closeTime'];
This should result in a warning
Warning: Cannot use a scalar value as an array in ....
The issue that $lastPeriod = end($periods); gives you the value of the last element in the array. So if you have this array:
$dailyHours[0]['periods'][] = 23;
$dailyHours[0]['periods'][] = 12;
$dailyHours[0]['periods'][] = 5;
$dailyHours[0]['periods'][] = 8; //Last elements value in item 0
$dailyHours[1]['periods'][] = 23;
$dailyHours[1]['periods'][] = 11;
$dailyHours[1]['periods'][] = 3; //Last elements value in item 1
$dailyHours[2]['periods'][] = 5;
$dailyHours[2]['periods'][] = 12; //Last elements value in item 2
Therefore
$lastPeriod = end($periods);
would return the values 8,3 and 12.
A simplified version of your code with two loops. The outer loop ($i) and the inner loop ($j)
for ( $i = 0; $i < sizeof($dailyHours); $i++ ) {
$periods = $dailyHours[$i]['periods'];
for ($j = 0; $j < sizeof($periods); $j++) {
$lastPeriod = end($periods); //would give 8,8,8, 3,3,3 and 12,12,12
//This would basically mean that an associative array with key closeTime
//with the value of 8,3 or 12 => is the same as the value of $dailyHours[$i +
//1]['periods'][0]['closeTime'];
//This is not a thing PHP can handle and therefore you should reviece
//a warning "Cannot use a scalar value as an array..."
//(You simply cannot mix numbers and associative arrays in that manner)
$lastPeriod['closeTime'] = $dailyHours[$i + 1]['periods'][0]['closeTime'];
}
}
Another issue is that you're trying to set a value each iteration with the same key and therefore nothing happens:
for ( $i = 0; $i < sizeof($dailyHours); $i++ ) {
$periods = $dailyHours[$i]['periods'];
for ($j = 0; $j < sizeof($periods); $j++) {
$lastPeriod['closeTime'] = rand();
echo '<pre>';
echo $lastPeriod['closeTime'];
echo '</pre>';
}
}
A possible output of the loops above code could be:
1393399136
1902598834
1291208498
654759779
493592124
1469938839
929450793
325654698
291088712
$lastPeriod['closeTime'] would be 291088712 which is the last set value above (last iteration) but the previous values set are not stored anywhere.

Find number of distinct pairs of numbers whose sum is equal to some 'K' - PHP

Given an array, I would like to display the count of distinct pairs of elements whose sum is equal to K -
I've written code as below, but I am unable to put array_diff to good use :\
<?PHP
function numberOfPairs($a, $k) {
$cnt = 0;
for($i=0; $i<count($a); $i++){
for($j=$i; $j<count($a); $j++){
if($a[$i]+$a[$j] == $k){
$arrRes[$i][0] = $a[$i];
$arrRes[$i][1] = $a[$j];
$cnt++;
}
}
}
sort($arrRes);
//print $cnt;
$d = $cnt;
for($i=0; $i<count($arrRes); $i++){
for($j=0; $j<count($arrRes); $j++){
$diff = array_diff($arrRes[$i], $arrRes[$j]);
if($diff == null)
$d += 1;
}
}
print $d;
}
$a = [6,6,3,9,3,5,1];
$k = 12;
numberOfPairs($a, $k);
?>
Here, the output arrays with sum equal to 12 are, i.e, the result of $arrRes is -
[0] => Array ( [0] => 3 [1] => 9 )
[1] => Array ( [0] => 6 [1] => 6 )
[2] => Array ( [0] => 6 [1] => 6 )
[3] => Array ( [0] => 9 [1] => 3 )
The count is 4, but the count should be 2, as (6,6) and (3,9) are the only distinct pairs.
You can simplify your solution, by using fact that arrays in php are hashmaps:
function numberOfPairs($a, $k) {
$used=[];
for ($i=0; $i<count($a); $i++)
for ($j=$i+1; $j<count($a); $j++) {
$v1 = min($a[$i], $a[$j]);
$v2 = max($a[$i], $a[$j]);
if ($k == $v1+$v2)
$used[$v1.'_'.$v2] = true;
}
return count($used);
}
$a = [6,6,3,9,3,5,1];
$k = 12;
echo numberOfPairs($a, $k);
You can create a flat array with used numbers and check so that you don't use them again with in_array.
function numberOfPairs($a, $k) {
$cnt = 0;
$used=[];
for($i=0; $i<count($a); $i++){
for($j=$i; $j<count($a); $j++){
if($a[$i]+$a[$j] == $k && !in_array($a[$i], $used) && !in_array($a[$i],$used)){
$arrRes[$i][0] = $a[$i];
$arrRes[$i][1] = $a[$j];
$used[] = $a[$i];
$used[] = $a[$j];
$used = array_unique($used);
$cnt++;
}
}
}
sort($arrRes);
//print $cnt;
// Not sure what the code below does, but I just left it the way it was.
$d = $cnt;
for($i=0; $i<count($arrRes); $i++){
for($j=0; $j<count($arrRes); $j++){
$diff = array_diff($arrRes[$i], $arrRes[$j]);
if($diff == null)
$d += 1;
}
}
print $d;
}
$a = [6,6,3,9,3,5,1];
$k = 12;
numberOfPairs($a, $k);
Try it here https://3v4l.org/lDe5V
Sort array and move indexes from both ends until they are not overlapped that gets O(n log n) instead of O(n^2) in accepted answer
function numberOfPairs($a, $k) {
sort($a);
$i = 0;
$j = count($a)-1;
// save last inseted array to avoid duplicates
$last = [];
while($i < $j) {
$s = $a[$i] + $a[$j];
if($s == $k) {
$t = [$a[$i++], $a[$j--]];
// Check for duplicate
if ($t != $last) {
$d[] = [$a[$i++], $a[$j--]];
$last = $t;
}
}
elseif($s > $k) $j--;
else $i++;
}
return $d;
}
demo
This is my method for finding distinct pairs of addends given an array and a target sum.
array_count_values() will reduce the input array size by condensing duplicate addends and storing them as keys (and their number of occurrences as values).
ksort() is called to ensure that the addends are processed in ascending order. This is crucial to avoid processing addends that are beyond the midpoint of the number set.
each iteration, store addends that are "less than or equal to" half of k AND have a matching addend.
when the addend multiplied by 2 is "greater than or equal to" k, do not continue to iterate.
Code: (Demo)
function numberOfPairs($a,$k){
$a=array_count_values($a); // enable use of the very fast isset() function and avoid iterating duplicates
ksort($a); // order so that only the lower values need to be iterated
foreach($a as $num=>$occur){
if(($double=$num*2)>=$k){ // we are at or past the middle
if($double==$k && $occur>1) $result[]=[$num,$k-$num]; // addends are equal and 2 exist, store before break
break;
}elseif(isset($a[$k-$num])){ // matching addend found, store & continue
$result[]=[$num,$k-$num];
}
}
var_export($result);
}
$a = [6,6,3,9,3,5,1];
$k = 12;
numberOfPairs($a,$k);
Output:
array (
0 =>
array (
0 => 3,
1 => 9,
),
1 =>
array (
0 => 6,
1 => 6,
),
)
array_count_values() is probably the most expensive function call in the snippet, but it sets up all subsequent processes to be fast, concise, direct, and logical (and I think, readable).

Initializing a 2 dimensions array in PHP

I want to initializing a 2 dimensions Array in PHP and I don't know How to declare a 2d array of size (1,N) in php with all values as Zeros?
$Orders_C = array(1,N);
I am not sure if this is correct syntax or not.
PHP doesnot have 2d array ,but instead it has array of array. You can use the code below to initialize as you said.
$Orders_C=array_fill(0,1, array_fill(0, N,0));
Here the array_fill first return an array filled with 0 from index 0 to N.And again the same array is filled to the new array upto index 1.Hence you will get an array within array.
Generic solution for any count of columns and rows could be:
$maxRows = 5;
$maxCols = 5;
$orders = [];
for ($col = 0; $col < $maxCols; $col++) {
for ($row = 0; $row < $maxRows; $row++) {
$orders[$col] = $row;
}
}
And because you want 2d array like (1, N) then you can simplify it
$orders = [];
for ($i = 0; $i < $maxRows; $i++) {
$orders[0][] = 0;
}

Calculate the highest duplicate integers of two associative arrays

Given 2 associative arrays:
$fruits = array ( "d" => "lemon", "a" => "orange", "b" => "banana", "c" => "apple" );
$fruits2 = array ( "e" => "lemon", "f" => "apple", "g" => "melon", "h" => "apple" );
I would like to do something like:
for ( $n = count($fruits), $i = 0; $i < $n; $i++)
{
$test = (bool) $fruits[$i] == $fruits2[$i];
}
This can not work as I am using associative array. What would be the best way to go to achieve that? (This loops is going to be ran intensity so I would like to keep it as light as possible)
EDIT to give more detail on what I am trying to do:
Here is a better example of what I am trying to achieve:
$array = array ( 1,2,3,4,3,2 );
$array2 = array ( 9,6,3,4,3,2 );
$counts = array_count_values( $words );
$counts2 = array_count_values( $words2 );
Given the arrays above I need to calculate which array as the highest duplicate integers. Imagine a poker game, comparing two hands that each contain duplicate cards, how to evaluate which set of duplicate (whether double, triple or quadruple ) as the highest value.
Use array array_values ( array $input ) function and compare them.
$value1=array_values($fruits);
$value2=array_values($fruits2);
for ( $i = 0; $i < count($value1); $i++)
{
$test[] = $value1[$i] == $value2[$i] ? TRUE : FLASE;
}
Got it working this way :
$n = count($fruits);
for ( $i = 0; $i < $n; $i++)
{
$cur_vals_1 = each ($fruits);
$cur_vals_2 = each ($fruits2);
$sum1 += $cur_vals_1['key'] * $cur_vals_1['value'];
...
}
You're probably chasing the wrong solution. To find the highest duplicate in an array I'd use this (PHP 5.3+ syntax):
max(array_keys(array_filter(array_count_values($array), function ($i) { return $i >= 2; })))
Do this for both arrays and compare which result is higher. Trying to compare both against each other at the same time is too convoluted.
You don't need the ternary operator.
Also, be careful with count() as it will fail if your array is null.
They also need to be equal lengths or you'll get an error.
if( is_array($value1) && is_array($value2) && count($value1)==count($value2) ) {
for ( $i = 0; $i < count($value1); $i++)
{
$test[] = ($value1[$i] == $value2[$i]);
}
}

How to use 3 dimensional array in PHP

I'm doing some image processing in php and normally I never use array in php before.
I have to keep the value of rgb value of hold image in 3 dimensional array.
For example, rgbArray[][][]
the first [] is represent th weight, the second[] use to keep height and the last one is use to keep either red,greed or blue. How can i create an array in php that can keep this set of value.
Thank you in advance.
I think you're looking for a two dimensional array:
$rgbArray[$index] = array('weight'=>$weight, 'height'=>$height, 'rgb'=>$rgb);
But here is a 3 dimensional array that could make sense for what you're asking.
$rgpArray[$index] = array('red'=>array('weight'=>$weight, 'height'=>$height),
'green'=>array('weight'=>$weight, 'height'=>$height),
'blue'=>array('weight'=>$weight, 'height'=>$height));
Your example is a little confuse rgbArray[1][1][red], it looks like you want this:
$rgbArray = array(1 => array(1 => array('red' => 'value')));
echo $rgbArray[1][1]['red']; // prints 'value'
I recommend, as PMV said, to do next:
$rgbArray = array('weight' => 1, 'height' => 1, 'rgb' => 'red' );
or
$rgbArray = array();
$rgbArray['weight'] = 1; // int value
$rgbArray['height'] = 1; // int value
$rgbArray['rgb'] = 'red'; // string value
If it's not what you want please be more specific in order to be helped.
If yours array
$rgbArray = array('red'=>array('weight'=>$weight, 'height'=>$height),
'green'=>array('weight'=>$weight, 'height'=>$height),
'blue'=>array('weight'=>$weight, 'height'=>$height));
Then you can assign the value to rgbArray like
$weight = $rgbArray['red']['weight']
$height = $rgbArray['red']['height']
If yours array
$rgbArray = array('red'=>array($weight, $height),
'green'=>array($weight, $height),
'blue'=>array($weight, $height));
Then you can assign the value to rgbArray like
$weight = $rgbArray['red'][0]
$height = $rgbArray['red'][1]
Define three-dimensional array
$threeDimArray = array(array(
array("reza", "daud", "ome"),
array("shuvam", "himel", "izaz"),
array("sayanta", "hasib", "toaha")));
Printing three-dimensional array
for ($i=0; $i < count($threeDimArray); $i++) {
for ($j=0; $j < count($threeDimArray[$i]); $j++) {
for ($k=0; $k < count($threeDimArray[$i][$j]); $k++) {
echo $threeDimArray[$i][$j][$k];
echo " ";
}
echo "<br>";
}
}

Categories