foreach and current - php

<?php
$a = array(1, 2, 3, 4, 5);
foreach ($a as $key => $elem) {
echo "$key = $elem"; echo ' = ';
var_dump(current($a));\
}
?>
The output I get when running that is as follows:
0 = 1 = int(2)
1 = 2 = int(2)
2 = 3 = int(2)
3 = 4 = int(2)
4 = 5 = int(2)
Seems to me that this is the output I should be getting?:
0 = 1 = int(1)
1 = 2 = int(2)
2 = 3 = int(3)
3 = 4 = int(4)
4 = 5 = int(5)
I do current() before the for loop on $a and get int(1). Thus it seems like it's the foreach loop that's causing it to increment. But if that's the case why is it only doing it once?
If I call next() in the for loop it increments but not otherwise. Of course next() starts out at int(3) (ie. the value after int(2))..

From reading the PHP documention on current, it does not look like you should expect foreach to move the current pointer.
Please see:
http://php.net/manual/en/function.current.php
What's a bit confusing is that the each function does move the current pointer. So if you rewrite your array as a loop using each rather than foreach, then you will get the desired current behavior.
Here's your example rewritten with each(), which produces the expected results:
<?php
$a = array(1, 2, 3, 4, 5);
while ( list($key,$elem) = each($a)) {
echo "$key = $elem"; echo ' = ';
var_dump(current($a));
}
?>

current() uses the internal flag (pointer) and foreach uses it's own.
If you want to do this (which is kind of silly as you have the key in $key) you can use ArrayIterator

I just stumbled on the same problem, and I believe I have a theory.
Foreach doesn't access the array elements by value, it creates its own copy. However, while doing this, it increments the value returned by current() just once.
To check this:
<?php
$a = [0, 1, 2];
foreach ($a as &$val){ // accessing the array elts by reference this time
var_dump(current($a));
}
/*this outputs:
int(1)
int(2)
bool(false)*/

Related

get the sum and difference of two associate array in php

I have 2 arrays.
arr1 =array('cat'=>5,'dog'=>2);
arr2 = array('cat'=>1,'dog'=>2);
I need to get the sum of 2 arrays and the difference of these arrays.
arr3 = array(cat =>6,dog =>4);
arr4 = array(cat =>4 ,dog =>0);
I tried USING array_merge,array_diff,array_combine
But nothing gives me what i need.
plz help
Assuming we have the same number of like keys in both arrays we can iterate through one or the other and find and work with the corresponding values belonging to the other identified by the same named keys.
<?php
$a1 = array('cat'=>5,'dog'=>2);
$a2 = array('cat'=>1,'dog'=>2);
foreach($a1 as $k => $v)
{
$add[$k] = $v + $a2[$k];
$sub[$k] = $v - $a2[$k];
}
var_dump($add, $sub);
Output:
array(2) {
["cat"]=>
int(6)
["dog"]=>
int(4)
}
array(2) {
["cat"]=>
int(4)
["dog"]=>
int(0)
}
You could always resolve the first problem with array_sum.
Second is more interesting, I'd solve it with an array_map. See it in action here
$subtracted = array_map(function ($x, $y) {
return $x - $y;
}, $arr1, $arr2);
$result = array_combine(array_keys($arr1), $subtracted);
Note that you can also solve the first problem by replacing - with + in the above example.
Also note that array_map tends to be generally more readable.
Simple foreach can do it, below example if some key is missing and just getting difference not in -ve Negative sign, the difference would be 4 not -4 for 1 cat - 5 cat
<?php
$arr1 =array('cat'=>5,'dog'=>2);
$arr2 = array('cat'=>1,'dog'=>2);
$sum= [];
$sub= [];
foreach(array_merge($arr1,$arr2) as $k=>$v){
$a1 = $arr1[$k] ?? 0;
$a2 = $arr2[$k] ?? 0;
$sum[$k] = $a1 + $a2;
$sub[$k] = abs($a1 - $a2);
}
print_r($sum);
print_r($sub);
?>
Live Demo
With simple foreach loop
If some data exist only in single array

Changing values of multidimensional array php

Its my first time working with multidimensional arrays in php. I need to change the second number in each sub array.
What I want is to check if the Id in the array matches the Id from the database. When the two match I want to change the 2nd entry in the sub array by adding a number to it. If the Id from the query does not match anything in the list I want a new sub array to be pushed to the end of the array with the values of Id and points_description.
Also, if its helpful, my program right now does find the matches. The only thing is, it does not update the 2D array.
$array = array(array());
while ($row_description = mysqli_fetch_array($query_description)) {
$check = 1;
$is_match = 0;
foreach ($array as $i) {
foreach ($i as $value) {
if ($check == 1) {
if ($row_description['Id'] == $value) {
//$array[$i] += $points_description;
$is_match = 1;
}
}
$check++;
$check %= 2; //toggle between check and points
}
}
if ($is_match == 0) {
array_push($array, array($row_description['Id'], $points_description));
}
}
I feel like Im doing this so wrong. I just want to go through my 2D array and change every second value. The expected output should be a print out of all the Ids and their corresponding point value
I hope this is helpful enough.
Example: $row_description['Id'] = 2 and $array = array(array(2,1), array(5,1) , array(6,1))
output should be $array = array(array(2,4), array(5,1) , array(6,1))
if $row_description['Id'] = 3 and $array = array(array(2,1), array(5,1) , array(6,1))
output should be $array = array(array(2,4), array(5,1) , array(6,1),array(3,3))
By default PHP will copy an array when you use it in a foreach.
To prevent PHP from creating this copy you need to use to reference the value with &
Simple example :
<?php
$arrFoo = [1, 2, 3, 4, 5,];
$arrBar = [3, 6, 9,];
Default PHP behavior : Make a copy
foreach($arrFoo as $value_foo) {
foreach($arrBar as $value_bar) {
$value_foo *= $value_bar;
}
}
var_dump($arrFoo);
/* Output :
array(5) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
[3]=>
int(4)
[4]=>
int(5)
}
*/
ByReference : Don't create the copy :
foreach($arrFoo as &$value_foo) {
foreach($arrBar as $value_bar) {
$value_foo *= $value_bar;
}
}
var_dump($arrFoo);
/* Output :
array(5) {
[0]=>
int(162)
[1]=>
int(324)
[2]=>
int(486)
[3]=>
int(648)
[4]=>
&int(810)
}
*/

What is array_slice()?

update
I'm new to PHP development: I looked on the PHP website for a function - array_slice. I read and looked at the example but I don't understand it. Can someone explain this in clear words for me?
I think it works as follow?
$example = array(1,2,3,4,5,6,7,8,9);
$offset = 2;
$length = 5;
$newArray = array_slice($example, offset, length);
the result of $newArray is: $newArray(3,4,5,6,7);
In addition to stefgosselin's answer that has some mistakes: Lets start with his array:
$input = array(1,2,3);
This contains:
array(3) {
[0]=> int(1)
[1]=> int(2)
[2]=> int(3)
}
Then you do array_slice:
var_dump(array_slice($input, 1));
The function will return the values after the first element (thats what the second argument, the offset means). But notice the keys!
array(2) {
[0]=> int(2)
[1]=> int(3)
}
Keep in mind that keys aren't preserved, until you pass true for the fourth preserve_keys parameter. Also because there is another length parameter before this, you have to pass NULL if you want to return everything after the offset, but with the keys preserved.
var_dump(array_slice($input, 1, NULL, true));
That will return what stefgosselin (incorrectly) wrote initially.
array(2) {
[1]=> int(2)
[2]=> int(3)
}
This function returns a subset of the array. To understand the example on the man page you have to understand array keys start at 0, ie
$array_slice = $array(1,2,3);
The above contains this:
$array[0] = 1,
$array[1] = 2,
$array[2] = 3
So, array_slice(1) of $array_sliced would return:
$arraysliced = array_slice($array_slice, 1);
$arraysliced[1] = 2;
$arraysliced[2] = 3;
It returns the part of your input array that starts at your defined offset, of the your defined length.
Think of it this way:
$output = array();
for ($i = 0; $i++; $i < count($input)) {
if ($i < $start)
continue;
if ($i > $start + $length)
break;
$output[] = $input[$i];
}
Basically its an skip and take operation. Skip meaning to jump to that element. Take meaning how many.
PHP has a built - in function, array_slice() , that you can use to extract a range of elements from an
array. To use it, pass it the array to extract the slice from, followed by the position of the first element in
the range (counting from zero), followed by the number of elements to extract. The function returns a new
array containing copies of the elements you extracted (it doesn ’ t touch the original array). For example:
$authors = array( “Steinbeck”,
“Kafka”, “Tolkien”, “Dickens” );
$authorsSlice = array_slice(
$authors, 1, 2 ); // Displays “Array
( [0] = > Kafka [1] = > Tolkien )”
print_r( $authorsSlice );
By the way, if you leave out the third argument to array_slice() , the function extracts all elements
from the start position to the end of the array:
$authors = array( “Steinbeck”, “Kafka”, “Tolkien”, “Dickens” );
$authorsSlice = array_slice( $authors, 1 );
// Displays “Array ( [0] = > Kafka [1] = > Tolkien [2] = > Dickens )”;
print_r( $authorsSlice );
Earlier you learned that array_slice() doesn ’ t preserve the indices of elements taken from an indexed
array. If you want to preserve the indices, you can pass a fourth argument, true , to array_slice() :
$authors = array( “Steinbeck”, “Kafka”, “Tolkien”, “Dickens” );
// Displays “Array ( [0] = > Tolkien [1] = > Dickens )”;
print_r( array_slice( $authors, 2, 2 ) );
// Displays “Array ( [2] = > Tolkien [3] = > Dickens )”;
print_r( array_slice( $authors, 2, 2, true ) );

Cleanest way of working out next variable name based on sequential order?

Hope my title explains it ok! Here's more detail:
I'm creating an array which stores keys & their values. Eg.
test1 = hello
test2 = world
test3 = foo
What is the cleanest way of working out what to call the next key? Let's say I will know the first part is 'test', but I don't know what the highest value number is. Obviously in this case I want it to be called 'test4'.
In the example below I want the next key to be 'test46', as it is the next highest value:
test6 = blah
test45 = boo
test23 = far
This sounds like you should be using an array with numerical indexes instead.
You could however use some code like this...
$arr = array('test6', 'test45', 'test23');
$max = 0;
foreach($arr as $value) {
$number = filter_var($value, FILTER_SANITIZE_NUMBER_INT);
$max = max($max, $number);
}
$newKey = 'test' . ++$max; // string(6) "test46"
CodePad.
Implementation of #alex answer without using a loop:
$arr = array('test6', 'test45', 'test23');
$max = max(filter_var_array($arr, FILTER_SANITIZE_NUMBER_INT));
$newKey = 'test' . ++$max; // string(6) "test46"
CodePad
This data structure would be better stored as an array.
$test = array();
$test[] = 'hello';
$test[] = 'world';
$test[] = 'foo';
You then don't need to know the highest number to add a new item, just use the empty brackets syntax (shown above) to add an item to the end of the array.
You then have access to a wealth of array functions that PHP gives you to work with your data: http://php.net/manual/en/ref.array.php
When you want to get item 43 from the array, use:
echo $test[42];
Arrays are counted from 0 rather than 1, so item 43 will have an index of 42.
What are you using that for? If numbering the array is a must-have, just use a simple numerical indexed array instead, and simply prepend the key with "test" if you need it to show up as "test1":
<?php
$array = array(
6 => 'blah',
45 => 'boo',
23 => 'bar'
);
$array[] = 'new';
echo $array[46] . "\n"; // this is 'new'
foreach( $array as $key => $value ) {
echo "test$key = $value<br />\n"; // test6 = blah
}

(PHP) Checking items in an array

I have an array like this:
Array(a,b,c,a,b)
Now, if I would like to check how many instances of "b" I can find in the array, how would I proceed?
See the documentation for array_count_values(). It seems to be what you are looking for.
$array = array('a', 'b', 'c', 'a', 'b');
$counts = array_count_values($array);
printf("Number of 'b's: %d\n", $counts['b']);
var_dump($counts);
Output:
Number of 'b's: 2
array(3) {
["a"]=> int(2)
["b"]=> int(2)
["c"]=> int(1)
}
Use array_count_values($arr). This returns an associative array with each value in $arr as a key and that value's frequency in $arr as the value. Example:
$arr = array(1, 2, 3, 4, 2);
$counts = array_count_values($arr);
$count_of_2 = $counts[2];
You can count the number of instances by using this function..
$b = array(a,b,c,a,b);
function count_repeat($subj, $array) {
for($i=0;$i<count($array);$i++) {
if($array[$i] == $subj) {
$same[] = $array[$i]; //what this line does is put the same characters in the $same[] array.
}
return count($same);
}
echo count_repeat('b', $b); // will return the value 2
Although there are some fancy ways, a programmer should be able to solve this problem using very basic programming operators.
It is absolutely necessary to know how to use loops and conditions.
$count = 0;
$letters= array("a","b","c","a","b");
foreach ($letters as $char){
if ($char == "b") $count = $count+1;
}
echo $count.' "b" found';
NOT a rocket science.

Categories