All I am trying to do is flatten an arbitrary array of integers.
Here is my code:
<?php
$list_of_lists_of_lists = [[1, 2, [3]], [4, 3, 4, [5, 3, 4]], 3];
$flattened_list = [];
function flatten($l){
foreach ($l as $value) {
if (is_array($value)) {
flatten($value);
}else{
$flattened_list[] = $value;
}
}
}
flatten($list_of_lists_of_lists);
print_r($flattened_list);
?>
When I run this code, I get this:
Array ( )
I have no idea why. I did the exact same code in Python and it worked fine.
Can you guys point out, where I went wrong?
First you have a scope issue, that your result array is out of scope in the function. So just pass it as argument from call to call.
Second you also don't return your result array, which you have to do, if you want to use the result outside of the function.
Corrected code:
$list_of_lists_of_lists = [[1, 2, [3]], [4, 3, 4, [5, 3, 4]], 3];
function flatten($l, $flattened_list = []){
foreach ($l as $value) {
if(is_array($value)) {
$flattened_list = flatten($value, $flattened_list);
} else {
$flattened_list[] = $value;
}
}
return $flattened_list;
}
$flattened_list = flatten($list_of_lists_of_lists);
print_r($flattened_list);
output:
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 3
[5] => 4
[6] => 5
[7] => 3
[8] => 4
[9] => 3
)
Related
there is a multidimensional array like
[["14","16"],["26"],["24"],["5","8"]]
the length of the total array is not limited, nested will be an average of 1-3 elements
nested ones will always be numbers, not arrays, i.e. the array is two-dimensional. the task is to get a "each with each" relationship, i.e. I should get sets of the kind
14,26,24,5;
14,26,24,8;
16,26,24,5;
16,26,24,8;
I tried cycles, and tried recursion, but it doesn’t work.
Can you help me please?
Thanks
$data = [
[2, 4],
[],
[3, 6],
[2, 3],
];
$output = array_reduce($data, function (array $carry = null, array $item = null): array {
if (!$carry) {
return $item;
}
if (!$item) {
return $carry;
}
$output = [];
foreach ($carry as $foo) {
foreach ($item as $bar) {
$output[] = $foo . '-' . $bar;
}
}
return $output;
});
print_r($output);
Output:
Array
(
[0] => 2-3-2
[1] => 2-3-3
[2] => 2-6-2
[3] => 2-6-3
[4] => 4-3-2
[5] => 4-3-3
[6] => 4-6-2
[7] => 4-6-3
)
While working on a project which checks the if Laravel models are related to each other I noticed some (weird?) pointer behavior going on with PHP. Below is a minimal example to reproduce what I found.
<?php
$arr = ['a', 'b', ['c']];
foreach($arr as &$letter) {
if (!is_array($letter)) {
$letter = [$letter];
}
}
dump($arr);
foreach($arr as $letter) {
dump($arr);
}
function dump(...$dump) {
echo '<pre>';
var_dump($dump);
echo '</pre>';
}
At first I expected the dumps in this response to all return the same data:
[ ['a'], ['b'], ['c'] ]
But that is not what happened, I got the following responses:
[ ['a'], ['b'], ['c'] ]
[ ['a'], ['b'], ['a'] ]
[ ['a'], ['b'], ['b'] ]
[ ['a'], ['b'], ['b'] ]
A running example can be found here.
Why do the pointers act this way? How can I update $letter in the first loop without having to do $arr[$key] = $letter?
Edit: As people seem to be misunderstanding why there is a second foreach loop, this is to show that the array is changing without being reassigned
According to the PHP documentation:
Reference of a $value and the last array element remain even after the foreach loop. It is recommended to destroy it by unset().
$arr = array(1, 2, 3, 4);
foreach ($arr as &$value) {
$value = $value * 2;
}
// $arr is now array(2, 4, 6, 8)
// Without an `unset($value)`, `$value` is still a reference to the last item: `$arr[3]`
foreach ($arr as $key => $value) {
// $arr[3] will be updated with each value from $arr...
echo "{$key} => {$value} ";
print_r($arr);
}
// ...until ultimately the second-to-last value is copied onto the last value
/* output:
0 => 2 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 2 )
1 => 4 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 4 )
2 => 6 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 6 )
3 => 6 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 6 ) */
First of all: PHP doesn't have pointers, it has references. See What references are and What references are not for more information.
The reason this happens is that $letter after the foreach loop still holds a reference to the last element of your array (which is [c]). So in your second loop, you're overriding not only $letter while looping but also the reference it points to.
To solve the problem you need to unset($letter) after your first loop:
$arr = ['a', 'b', ['c']];
foreach($arr as &$letter) {
if (!is_array($letter)) {
$letter = [$letter];
}
}
unset($letter); // this is important
dump($arr);
foreach($arr as $letter) {
dump($arr);
}
function dump(...$dump) {
echo '<pre>';
var_dump($dump);
echo '</pre>';
}
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
Basically, I am fetching data from an API and that API has duplicate numbers. I want to count the duplicate numbers within the foreach, but its not working for some reason. I am not sure what I am doing wrong. You can see there is 33 many times. See the picture how it prints. It should be showing something like this
Array
(
[33] => 5
[2] => 3
)
Code:
foreach ($parsed_json1->numbers as $item) {
$ui = $item->no;
$currentp= number_format($ui, 6);
//echo $currentp;
//echo "</br>";
$array = array($currentp);
$vals = array_count_values($array);
//echo 'No. of NON Duplicate Items: '.count($vals).'<br><br>';
print_r($vals);
}
The fundamental flaw of your code is that you take one value and format it, then you put it into array and then do array_count_values on it.
See the difference:
$arr = [33, 32, 23, 33, 22, 23, 32, 33, 33];
print_r(array_count_values($arr));
foreach($arr as $a) {
$currentp= number_format($a, 6);
$array = array($currentp);
$vals = array_count_values($array);
print_r($vals);
}
First print_r prints:
Array
(
[33] => 4
[32] => 2
[23] => 2
[22] => 1
)
And the print_r inside foreach prints:
Array([33.000000] => 1)
Array([32.000000] => 1)
Array([23.000000] => 1)
Array([33.000000] => 1)
Array([22.000000] => 1)
Array([23.000000] => 1)
Array([32.000000] => 1)
Array([33.000000] => 1)
Array([33.000000] => 1)
Do you realize the difference?
I guess, what you need is
$arr = (array_count_values([33, 32, 23, 33, 22, 23, 32, 33, 33]));
$new_arr = [];
foreach($arr as $k => $a) {
$new_arr[number_format($k, 6)] = $a;
}
print_r($new_arr);
Which outputs:
Array
(
[33.000000] => 4
[32.000000] => 2
[23.000000] => 2
[22.000000] => 1
)
Not sure why you use number_format(), but I'm guessing you need something like this
$num_array = []; // Initialize number array
foreach ($parsed_json1->numbers as $item) {
$ui = $item->no;
$currentp= number_format($ui, 6);
$num_array[] = $currentp; // Store each number first to number array
}
// After foreach loop, do array_count_values to number array
$vals = array_count_values($num_array);
print_r($vals); //Print result
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