PHP - Use multiple values in foreach loop - php

I have the two PHP loops as below:
foreach ($directData as $key => $val) {
echo $val;
echo "|"; //Just for the visual.
}
foreach ($sdata as $key => $val) {
echo $val;
echo "|"; //Just for the visual.
}
Which output:
5|5|5|10|10|10|0| and the second: 2|2|2|5|5|5|20|
My question is, how can I combine these two result (add them) and print it out like above?
So, it would be:
7|7|7|15|15|15|20

php > $a = [1, 2, 3];
php > $b = [4, 5, 6];
php > $c = array_map(function($x, $y){ return $x + $y; }, $a, $b);
php > print_r($c);
Array
(
[0] => 5
[1] => 7
[2] => 9
)
php > print_r(implode($c, '|') . '|');
5|7|9|

Broken down for better readability, this will sum them into $new array.
array_map will iterate through both given arrays and apply the callback function to both of the arrays at their current indexes. The callback function will sum the values of at current indexes.
$new=array_map(
function(){
return array_sum(func_get_args());
},
$directData, $sdata
);
$out= '';
foreach ($new as $key => $val)
$out .= $val.'|';
echo rtrim($out,'|');

in simple way you can do it like:
$finalData = array_map(function () {
return array_sum(func_get_args());
}, $directData, $sdata );
print_r($finalData );

If each index corresponds in the arrays
$rezult = array();
for($i=0;$i<count($directData);$i++){
$rezult[] = $directData[$i] + $sdata[$i];
}
echo join("|",$rezult);

Here is a method that uses the iterators that all PHP arrays have.
/**
* Use the iterator that all PHP arrays have.
*
* Check both arrays for having entries.
*/
$listOut = array(); // output in here
while (current($listA) !== false && current($listB) !== false) {
$listOut[] = current($listA) + current($listB);
next($listA);
next($listB);
}
Input:
$listA = array(5, 5, 5, 10, 10, 10, 0);
$listB = array(2, 2, 2, 5, 5, 5, 20, );
Output
Array
(
[0] => 7
[1] => 7
[2] => 7
[3] => 15
[4] => 15
[5] => 15
[6] => 20
)
7| 7| 7| 15| 15| 15| 20

Related

Make new array values from element value plus the previous element's value

I have array like this :
$array = array(1, 4, 8, 3, 7);
I want sum the value of array but first, I unshift the array like this :
<?php
$array = array(1, 4, 8, 3, 7);
array_unshift($array, 0);
array_pop($array);
foreach($array as $key => $val) {
echo $val;
}
?>
then I want sum array first (1, 4, 8, 3, 7) with new array (0, 1, 4, 8, 3)
sum like 1 plus 0 and 4 plus 1 and 8 plus 4 etc
And I want the output is : 1, 5, 12, 11, 10
Just use array_map.
array_map allows you to use a custom function on multiple arrays at the same time
$array = array(1, 4, 8, 3, 7);
$others = $array;
array_unshift($others, 0);
array_pop($others);
function sumarray($v1,$v2){
return $v1+$v2;
}
$res = array_map('sumarray', $array,$others);
print_r($res);
result like
Array
(
[0] => 1
[1] => 5
[2] => 12
[3] => 11
[4] => 10
)
You can use for loop instead of foreach.
Example
$array = $array2 = array(1, 4, 8, 3, 7);
array_unshift($array, 0);
array_pop($array);
$array3 = [];
for($i = 0; $i < count($array); $i++) {
$array3[] = $array[$i]+$array2[$i];
}
print_r($array3);
Output
Array
(
[0] => 1
[1] => 5
[2] => 12
[3] => 11
[4] => 10
)
You can store the popped value in a variable (popped) so you can use it later. Then you can use a regular for loop to loop over your array and add the popped value to the array once the loop is complete:
$array = array(1, 4, 8, 3, 7);
array_unshift($array, 0);
$popped = array_pop($array);
$result = [];
for($i = 0; $i < count($array)-1; $i++) {
$val1 = $array[$i];
$val2 = $array[$i + 1];
$result[] = $val1 + $val2;
}
$result[] = end($array) + $popped; // add the last element with the popped value
print_r($result);
Output:
Array ( [0] => 1 [1] => 5 [2] => 12 [3] => 11 [4] => 10 )
There is no need to pop or shift any elements and there is no need to create a copy of the input array.
As you iterate the input array, sum the current value with the previous value. If there is no previous value, use zero. This is exceedingly simple since your input is an indexed array.
Code: (Demo)
$array = [1, 4, 8, 3, 7];
$result = [];
foreach ($array as $index => $value) {
$result[] = $value + ($array[$index - 1] ?? 0);
}
var_export($result);
// [1, 5, 12, 11, 10]

Filter 2d array to keep all rows which contain a specific value

I have a two dimensional haystack array like this:
[
4 => [0, 1, 2, 3, 10],
1 => [0, 1, 2, 3, 10],
2 => [0, 1, 2, 3],
3 => [0, 1, 2, 3]
]
Let's say that I have a search value of $x = 10.
How can I search in above array and get an array index which contains $x.
In my current example, subarrays with key 4 and 1 contain value of $x -- I need those 2 subarrays.
You could loop then use array_search()
$array = array(...); // Your array
$x = 10;
foreach ($array as $key => $value) {
if (array_search($x, $value)) {
echo 'Found on Index ' . $key . '</br>';
}
}
Or if you need the arrays with those index
$array = array(...); // Your array
$x = 10;
$result = array(); // initialize results
foreach ($array as $key => $value) {
if (array_search($x, $value)) {
$result[] = $array[$key]; // push to result if found
}
}
print_r($result);
You can use array_filter() to keep only the array that contains the value you want:
$array = array(
array(0, 1, 2, 3, 10),
array(0, 1, 2, 3, 10),
array(0, 1, 2, 3),
array(0, 1, 2, 3)
);
$x = 10;
$out = array_filter($array, function($arr) use($x) {
return in_array($x, $arr);
});
print_r($out);
Output:
Array
(
[0] => Array
(
[0] => 0
[1] => 1
[2] => 2
[3] => 3
[4] => 10
)
[1] => Array
(
[0] => 0
[1] => 1
[2] => 2
[3] => 3
[4] => 10
)
)
You can use as well in_array
$array = array(); // Your array
$x = 10;
$result = array(); // initialize results
foreach ($array as $key => $value) {
if (in_array($x, $value)) {
$result[] = $array[$key]; //
}
}
print_r($result)
You can use array_search() function to search the value in array..
Link: http://php.net/manual/en/function.array-search.php
For Exp:
$x = 10; // search value
$array = array(...); // Your array
$result = array(); // Result array
foreach ($array as $key => $value)
{
if (array_search($x, $value))
{
$result[] = $array[$key]; // push the matched data into result array..
}
}
print_r($result);
You can use array_search();
doc: http://www.php.net/manual/en/function.array-search.php

Getting specidic values from PHP arrays

Is there a way to get the first value from array, then the first value key + 3 ; then +6 then + 9 ans so on
Take this array for example,
array(1,2,5,14,19,2,11,3,141,199,52,24,16)
i want extract a value every 3 so the result would be
array(1,14,11,199,16)
Can i do that with existing PHP array function?
Use a for loop and increment the counter variable by 3.
for ($i = 0; $i <= count(your array); $i+3) {
echo $myarray[i]
}
The following is function that will handle extracting the values from a given array. You can specify the number of steps between each value and if the results should use the same keys as the original. This should work with regular and associative arrays.
<?php
function extractValues($array, $stepBy, $preserveKeys = false)
{
$results = array();
$index = 0;
foreach ($array as $key => $value) {
if ($index++ % $stepBy === 0) {
$results[$key] = $value;
}
}
return $preserveKeys ? $results : array_values($results);
}
$array = array(1, 2, 5, 14, 19, 2, 11, 3, 141, 199, 52, 24, 16);
$assocArray = array('a' => 1, 'b' => 2, 'c' => 5, 'd' => 14, 'e' => 19, 'f' => 2, 11, 3, 141, 199, 52, 24, 16);
print_r(extractValues($array, 3));
print_r(extractValues($array, 3, true));
print_r(extractValues($assocArray, 5));
print_r(extractValues($assocArray, 5, true));
?>
Output
Array
(
[0] => 1
[1] => 14
[2] => 11
[3] => 199
[4] => 16
)
Array
(
[0] => 1
[3] => 14
[6] => 11
[9] => 199
[12] => 16
)
Array
(
[0] => 1
[1] => 2
[2] => 52
)
Array
(
[a] => 1
[f] => 2
[4] => 52
)
Use a loop and check the key.
$result = array();
foreach($array as $key => $value) {
if ($key % 3 === 0) {
$result[] = $value;
}
}
Try below one:
<?php
$your_array = array (1,2,5,14,19,2,11,3,141,199,52,24,16);
$every_3 = array();
$i = 0;
foreach($your_value as $value) {
$i++;
if($i%3==0){
$every_3[]=$value;
}
}
var_dump($every_3);
?>
Do like this
$arr=array (1,2,5,14,19,2,11,3,141,199,52,24,16);
$narr=array();
for($i=0;$i<count($arr);$i=$i+3){
$narr[]=$arr[$i]
}
print_r($narr);
<?php
$mynums = array(1,2,5,14,19,2,11,3,141,199,52,24,16);
foreach ($mynums as $key => $value) {
if ( $key % 3 === 0)
{
$newnum[] = $value;
}
}
var_dump($newnum);
?>
$data = array(1,2,5,14,19,2,11,3,141,199,52,24,16);
$matches = array();
foreach($data as $key => $value)
{
if($key%3 === 0)
{
$matches[] = $value;
}
}
var_dump($matches);
The only way you could do it would be to use a loop, count the length of an array, and loop through using a % mathmatical operator.
It gives you a remainder of a division: http://au2.php.net/operators.arithmetic

Reference detection in array from another function

So I'm using the pin method, but the reference is detected one level too late:
$pin = time();
function wrap($arr){
test($arr);
}
function test(&$arr){
global $pin;
if(in_array($pin, $arr))
return print "ref";
$arr[] = $pin;
foreach($arr as &$v){
if($v != $pin){
if(is_array($v))
return test($v);
print $v . " ";
}
}
}
$array = array(1, 2, 3);
$array[4] = &$array;
wrap($array);
I get 1 2 3 1 2 3 rec
But I expect 1 2 3 rec
If I just do test($arr) then it works, but the problem is that I need to wrap the test function inside another one that accepts values not references :(
Is there any way I can detect the reference at the right moment with my wrapper function too?
Introduction
I think a better approach would be to create a copy of the array and compare modification rather than use global pin and it can still be a 100% Recursive
Example 1
This is from your example above :
$array = array(1,2,3);
$array[4] = &$array;
wrap($array);
Output
Array
(
[0] => 1
[1] => 2
[2] => 3
[4] => ref
)
Example 2
Are we really sure its detecting reference or just a copy of the array
//Case 1 : Expect no modification
$array = array(1, 2, 3, array(1, 2, 3));
wrap( $array);
//Case 2 : Expect Modification in Key 2
$array = array(1, 2, 3, array(1, 2, 3));
$array[2] = &$array;
wrap( $array);
Output
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
)
Array
(
[0] => 1
[1] => 2
[2] => ref
[3] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
)
Example 3
Is this really recursive ?
$array = array(1, 2, 3, array(1, 2, 3));
$array[4][4][2][6][1] = array(1,2,3=>&$array);
wrap( $array);
Output
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
[4] => Array
(
[4] => Array
(
[2] => Array
(
[6] => Array
(
[1] => Array
(
[0] => 1
[1] => 2
[3] => ref <-- GOT YOU
)
)
)
)
)
)
Your Modified Function
/**
* Added printf since test now returns array
* #param array $arr
*/
function wrap(array $arr) {
printf("<pre>%s<pre>", print_r(test($arr), true));
}
/**
* - Removed Top Refrence
* - Removed Global
* - Add Recursion
* - Returns array
* #param array $arr
* #return array
*/
function test(array $arr) {
$temp = $arr;
foreach ( $arr as $key => &$v ) {
if (is_array($v)) {
$temp[$key]['_PIN_'] = true;
$v = isset($arr[$key]['_PIN_']) ? "ref" : test($v);
}
}
unset($temp); // cleanup
return $arr;
}
I think you are over-complicating things. I solved this by looping over the array and checking if the current value in the array is equivalent (===) with the array.
function wrap( $arr){
test($arr);
}
function test( $arr){
foreach( $arr as $v) {
if( $v === $arr) {
print 'ref, ';
} else {
if( is_array( $v)) {
test( $v);
} else {
print $v . ', ';
}
}
}
}
I used the following test cases:
echo "Array 1:\n";
$array1 = array(1, 2, 3);
$array1[4] = &$array1;
wrap( $array1);
echo "\nArray 2:\n";
$array2 = array(1, 2, 3, array(1, 2, 3));
$array2[2] = &$array2;
wrap( $array2);
Which produced this output:
Array 1:
1, 2, 3, ref
Array 2:
1, 2, ref, 1, 2, 3,
However, the above method will fail for nested references. If nested references are possible, as in the following test case:
echo "\nArray 3:\n";
$array3 = array(1, 2, 3, array(1, 2, 3));
$array3[3][2] = &$array3;
wrap( $array3);
Then we need to keep track of all the array references we've seen, like this:
function wrap( $arr){
test( $arr);
}
function test( $arr){
$refs = array(); // Array of references that we've seen
$f = function( $arr) use( &$refs, &$f) {
$refs[] = $arr;
foreach( $arr as $v) {
if( in_array( $v, $refs)) {
print 'ref, ';
} else {
if( is_array( $v)) {
$f( $v);
} else {
print $v . ', ';
}
}
}
};
$f( $arr);
}
Using the above test case, this outputs:
Array 3:
1, 2, 3, 1, ref, 3,
Edit: I've updated the final function that keeps track of all references to eliminate the global dependencies.
function wrap($arr){ test($arr); }
/// ...
wrap($array);
Your wrap() function allocates new memory block for $arr. When you calling test() function within wrap()s body, it takes reference of $arr memory block, but not an $arrays memory block, because $arr is a copy of $array and PHP memory management system stores them separately.
There is a universal reference spotting function:
function is_equal_refs(&$a, &$b){
$buffer = $a; // saving current value in temporary variable
$a = md5(time()); // assigning new value to memory block, pointed by reference
$result = ($a === $b); // if they're still equal, then they're point to the same place.
$a = $buffer; // restoring value
return $result; // returning result
}
So, lets do some testing:
<?php
header('Content-Type: text/plain');
function is_equal_refs(&$a, &$b){
$buffer = $a;
$a = md5(time());
$result = ($a === $b);
$a = $buffer;
return $result;
}
function wrap($arr){ test($arr); }
function test(&$arr){
foreach($arr as &$v){
if(is_equal_refs($arr, $v)){
print_r('ref');
echo PHP_EOL;
break;
}
if(is_array($v))return test($v);
print_r($v);
echo PHP_EOL;
}
}
$array = array(1, 2, 3);
$array[] = &$array;
wrap($array);
?>
Shows:
1 // < $arr
2
3
1 // < $array
2
3
ref // < $array doubled -> reference found
The reason of such behavior is $arr[3] contains reference for $arrays memory block, but not reference of itself's memory block.
Lets remove a $array[] = &$array; row, and modify wrap() function to check:
function wrap($arr){
$arr[] = &$arr;
test($arr);
}
And result would be:
1 // < $arr
2
3
ref // < $arr doubled -> reference found
Because $arr not points to $array, but to itself in $arr[3]. So, in your code there are different references you want to spot.
CONCLUSION: What you want to achieve is breaking out PHP memory management rules.
UPDv1:
Need to seek a workaround, to restore $array reference in a wrap() function scope.
1) A "bad" / "globals" practice:
<?php
header('Content-Type: text/plain');
function is_equal_refs(&$a, &$b){
$buffer = $a;
$a = md5(time());
$result = ($a === $b);
$a = $buffer;
return $result;
}
function wrap($array){
global $check; // <- THIS
test(empty($check) ? $array : $check); // <- THIS
}
function test(&$arr){
foreach($arr as &$v){
if(is_equal_refs($v, $arr)){
print_r('ref');
echo PHP_EOL;
break;
}
if(is_array($v)){
test($v);
} else {
print $v . ' ';
echo PHP_EOL;
}
}
}
$array = array(1, 2, 3);
$array[] = &$array;
$check = &$array; // <- and THIS
wrap($array);
?>
Which shows:
1
2
3
ref
2) A "wrap everything in array or object" practice: (prefered and reliable)
<?php
header('Content-Type: text/plain');
define('REF_MARKER', 'x-my-tr!cky-ref'); // trick key definition
function is_equal_refs(&$a, &$b){
$buffer = $a;
$a = md5(time());
$result = ($a === $b);
$a = $buffer;
return $result;
}
function wrap(array $arr){
// restore reference, if trick.
// it might be moved to the top part of test() function (might affect performance).
if(isset($arr[REF_MARKER]))$arr = &$arr[REF_MARKER];
test($arr);
}
// $array - subject to test;
// $refs - internal ref list of all `subjects`;
function test(&$array, $refs = array()){
$refs[] = &$array;
foreach($array as &$value){
foreach($refs as &$ref){
if(is_equal_refs($ref, $value))return print 'ref ';
}
if(is_array($value)){
$refs[] = &$value;
test($value, $refs);
} else {
print $value . ' ';
}
}
}
$array = array(1, 2, 3);
$array[] = &$array;
wrap(array(REF_MARKER => &$array)); // trick
print PHP_EOL;
$ring = array(1, 2, 3, array(4, 5, 6));
$ring[3][] = &$ring;
wrap(array(REF_MARKER => &$ring)); // trick
print PHP_EOL;
$test = array('a', 'b', 'c');
$ring = array(1, 2, 3);
$ring[] = &$test;
$test[] = &$ring;
wrap(array(REF_MARKER => &$ring)); // trick
print PHP_EOL;
wrap(range(1, 5)); // normal
print PHP_EOL;
$test = array(1, 2, 3, array(1, 2, 3), 4, array(5, 2, 3), array(6, array(1, 2, 3), 7), array(1, 2, 3));
wrap($test); // normal
print PHP_EOL;
$test[] = &$test;
$test[3][] = &$test;
$test[5][] = &$test[3];
wrap(array(REF_MARKER => &$test)); // trick
?>
Shows:
1 2 3 ref
1 2 3 4 5 6 ref
1 2 3 a b c ref
1 2 3 4 5
1 2 3 1 2 3 4 5 2 3 6 1 2 3 7 1 2 3
1 2 3 1 2 3 ref 4 5 2 3 ref 6 1 2 3 7 1 2 3 ref

Filter array - odd even

How can a filter out the array entries with an odd or even index number?
Array
(
[0] => string1
[1] => string2
[2] => string3
[3] => string4
)
Like, i want it remove the [0] and [2] entries from the array.
Or say i have 0,1,2,3,4,5,6,7,8,9 - i would need to remove 0,2,4,6,8.
foreach($arr as $key => $value) if($key&1) unset($arr[$key]);
The above removes odd number positions from the array, to remove even number positions, use the following:
Instead if($key&1) you can use if(!($key&1))
Here's a "hax" solution:
Use array_filter in combination with an "isodd" function.
array_filter seems only to work on values, so you can first array_flip and then use array_filter.
array_flip(array_filter(array_flip($data), create_function('$a','return $a%2;')))
You could also use SPL FilterIterator like this:
class IndexFilter extends FilterIterator {
public function __construct (array $data) {
parent::__construct(new ArrayIterator($data));
}
public function accept () {
# return even keys only
return !($this->key() % 2);
}
}
$arr = array('string1', 'string2', 'string3', 'string4');
$filtered = array();
foreach (new IndexFilter($arr) as $key => $value) {
$filtered[$key] = $value;
}
print_r($filtered);
<?php
function odd($var)
{
// returns whether the input integer is odd
return($var & 1);
}
function even($var)
{
// returns whether the input integer is even
return(!($var & 1));
}
$array1 = array("a"=>1, "b"=>2, "c"=>3, "d"=>4, "e"=>5);
$array2 = array(6, 7, 8, 9, 10, 11, 12);
echo "Odd :\n";
print_r(array_filter($array1, "odd"));
echo "Even:\n";
print_r(array_filter($array2, "even"));
?>
Odd :
Array
(
[a] => 1
[c] => 3
[e] => 5
)
Even:
Array
(
[0] => 6
[2] => 8
[4] => 10
[6] => 12
)
I'd do it like this...
for($i = 0; $i < count($array); $i++)
{
if($i % 2) // OR if(!($i % 2))
{
unset($array[$i]);
}
}
<?php
$array = array(0, 3, 5, 7, 20, 10, 99,21, 14, 23, 46);
for ($i = 0; $i < count($array); $i++)
{
if ($array[$i]%2 !=0)
echo $array[$i]."<br>";
}
?>
$array = array(0 => 'string1', 1 => 'string2', 2 => 'string3', 3 => 'string4');
// Removes elements of even-numbered keys
$test1 = array_filter($array, function($key) {
return ($key & 1);
}, ARRAY_FILTER_USE_KEY);
// Removes elements of odd-numbered-keys
$test2 = array_filter($array, function($key) {
return !($key & 1);
}, ARRAY_FILTER_USE_KEY);
This answer is a bit of an improvement over this answer. You can use anonymous functions instead of create_function. Also, array_filter takes an optional flag parameter that lets you specify that the callback function takes the key as its only argument. So you don't need to use array_flip to get an array of keys.

Categories