I've written the below function, it takes in a 2 dimensional array and return the number of times a key occurs, BUT it feels like i may be reinventing the wheel here, is there an easy way?
function countKeys($array, $key)
{
$results = array();
foreach($array as $row)
{
if (array_key_exists($row[$key], $results))
{
$results[$row[$key]] += 1;
}
else
{
$results[$row[$key]] = 1;
}
}
return $results;
}
To count the keys in a two dimensional array with a search I would do this -
function countKeys($array,$search){
$key_count = array(); // new array
foreach($array as $record) {
$keys = array_keys($record);
foreach($keys as $key){
if($key == $search){ // check against the search term
array_push($key_count, $key); // add the key to the new array
}
}
}
return count($key_count); // just count the new array
}
echo countKeys($records, 'last_name');
EXAMPLE
array_keys()
count()
For a 2 dimensional array try:
$result = count(array_column($array, $key));
PHP >= 5.5.0 needed for array_column() or use the PHP Implementation of array_column()
Just use count() function like:
count($array);
see: http://php.net/manual/pt_BR/function.count.php
You can use this function to count arrays variable as well.
Hope it helps you.
Related
on http://php.net/manual/en/function.in-array.php - if you scroll down it gives a function to determine if a string is inside of a query in a multidimensional array. "If you found yourself in need of a multidimensional array in_array like function you can use the one below. Works in a fair amount of time"
Here's original code(working):
function in_multiarray($elem, $array)
{
$top = sizeof($array) - 1;
$bottom = 0;
while($bottom <= $top)
{
if($array[$bottom] == $elem)
return true;
else
if(is_array($array[$bottom]))
if(in_multiarray($elem, ($array[$bottom])))
return true;
$bottom++;
}
return false;
}
What I'm trying to do is instead of returning 'true' or 'false' - i'd like to return the ROW #. So my initial thought was to simply replace 'return true' with 'return $bottom; however it isn't returning the record number.
Modified Function (not working);
function in_multiarray($elem, $array)
{
$top = sizeof($array) - 1;
$bottom = 0;
while($bottom <= $top)
{
if($array[$bottom] == $elem)
return $bottom;
else
if(is_array($array[$bottom]))
if(in_multiarray($elem, ($array[$bottom])))
return $bottom;
$bottom++;
}
return false;
}
Does anyone have an idea how to modify this function to return the ROW number that contains the match?
Here's a sample of the array...
$sample = array
array ("oldpage1.php","newpage1.php"),
array ("oldpage2.php","newpage2.php"),
array ("oldpage3.php","newpage3.php"),
array ("oldpage4.php","newpage4.php"),
array ("oldpage5.php","newpage5.php")
etc.
);
$row = in_multiarray($input, $sample);
Therefore if we know the row # we can fetch the new page with a simple
$newpage=$sample[$row][1]
Thanks!
It's worth noting that a function like in_array is intended to tell you whether or not a value exists inside of an array. What you're looking for seems to be a lot closer to something like array_search, which is designed to actually provide you with the key that points to a given value in the array.
However, because you're using a multi-dimensional array what you're actually looking for is the key that points to the array that contains the value. Hence we can divide and conquer this problem with two simple steps.
Map
Filter
The first step is to map a function in_array to every element in the first array (which is just another array). This will tell us which elements of the primary array contain an array that contains the value we're searching for.
$result = array_map(function($arr) use($search) {
return in_array($search, $arr, true);
}, $arr, [$searchValue]);
The second step is to then return the keys to those arrays (i.e. filter the result).
$keys = array_keys(array_filter($result));
Now you have all the keys of any matching items. If you want to apply as just one custom filter that specifies exactly where in the subarray to look, you could also do it like this.
$search = "oldpage2.php";
$sample = [
["oldpage1.php","newpage1.php"],
["oldpage2.php","newpage2.php"],
["oldpage3.php","newpage3.php"],
["oldpage4.php","newpage4.php"],
["oldpage5.php","newpage5.php"],
];
$keys = array_keys(array_filter($sample, function($arr) use($search) {
return $arr[0] === $search;
}));
var_dump($keys);
And you get...
array(1) {
[0]=>
int(1)
}
So now you know that "oldpage2.php" is in row 1 in $sample[1][0] which means you can do this to get the results out of the array.
foreach($keys as $key) {
echo "{$sample[$key][0]} maps to {$sample[$key][1]}\n";
}
Giving you
oldpage2.php maps to newpage2.php
If you want to return only the first result you could do that as well with a function like this using similar approach.
function getFirstMatch($search, Array $arr) {
foreach($arr as $key => $value) {
if ($value[0] === $search) {
return $value[1];
}
}
}
echo getFirstMatch("oldpage4.php", $sample); // newpage4.php
The Better Alternative
Of course, the better approach is to actually use the oldpage names as the actual keys of the array rather than do this expensive search through the array, because array lookup by key in PHP is just an O(1) operation, whereas this needle/haystack approach is O(N).
So we turn your $samples array into something like this and the search no longer requires any functions...
$samples = [
"oldpage1.php" => "newpage1.php",
"oldpage2.php" => "newpage2.php",
"oldpage3.php" => "newpage3.php",
"oldpage4.php" => "newpage4.php",
"oldpage5.php" => "newpage5.php",
];
Now you can just do something like $newpage = $samples[$search] and you get exactly what you're looking for. So echo $samples["oldpage2.php"] gives you "newpage2.php" directly without the intermediary step of searching through each array.
You can use the following code to get the full path to the value:
function in_multiarray($elem, $array, &$result)
{
$top = sizeof($array) - 1;
$bottom = 0;
while($bottom <= $top)
{
if($array[$bottom] == $elem) {
array_unshift($result, $bottom);
return true;
}
else {
if(is_array($array[$bottom])) {
if(in_multiarray($elem, $array[$bottom], $result)) {
array_unshift($result, $bottom);
return true;
}
}
}
$bottom++;
}
array_shift($result);
return false;
}
$sample = array(
array ("oldpage1.php","newpage1.php"),
array ("oldpage2.php","newpage2.php"),
array ("oldpage3.php","newpage3.php"),
array ("oldpage4.php","newpage4.php"),
array ("oldpage5.php","newpage5.php")
);
$input = "newpage5.php";
$result = [];
in_multiarray($input, $sample, $result);
print_r($result);
Path is stored in $result;
$data = array
(
array("Ravi","Kuwait",350),
array("Sameer","UK",400),
array("Aditi","Switzerland",50),
array("Akshay","India",250),
array("rishi","Singapore",200),
array("Mukul","Ireland",100)
);
I want to put condition to the third row such that I can get entries of less than 300.
I suppose that you meant "the third element" in each nested array.Use array_filter function to get an array of elements, those third element's value is less than 300:
$result = array_filter($data, function($v) { return $v[2] < 300; });
print_r($result);
Try this code:
<?php
$data = array
(
array("Ravi","Kuwait",350),
array("Sameer","UK",400),
array("Aditi","Switzerland",50),
array("Akshay","India",250),
array("rishi","Singapore",200),
array("Mukul","Ireland",100)
);
$newArray = array();
foreach($data as $key => $value)
{
if($value[2] <= 100)
$newArray[] = $value;
}
print_r($newArray);
?>
You can achieve this using the PHP function array_filter() :
PHP
function limitArray($array) {
return ($array[2] <= 300);
}
print_r(array_filter($data, 'limitArray'));
evalIN
I have a :
$value = "val";
I also have an array :
$keys = ['key1', 'key2', 'key3'...]
The keys in that array are dynamically generated, and can go from 2 to 10 or more entries.
My goal is getting this :
$array['key1']['key2']['key3']... = $value;
How can I do that ?
Thanks
The easiest, and least messy way (ie not using references) would be to use a recursive function:
function addArrayLevels(array $keys, array $target)
{
if ($keys) {
$key = array_shift($keys);
$target[$key] = addArrayLevels($keys, []);
}
return $target;
}
//usage
$keys = range(1, 10);
$subArrays = addARrayLevels($keys, []);
It works as you can see here.
How it works is really quite simple:
if ($keys) {: if there's a key left to be added
$key = array_shift($keys); shift the first element from the array
$target[$key] = addArrayLevels($keys, []);: add the index to $target, and call the same function again with $keys (after having removed the first value). These recursive calls will go on until $keys is empty, and the function simply returns an empty array
The downsides:
Recursion can be tricky to get your head round at first, especially in complex functions, in code you didn't write, but document it well and you should be fine
The pro's:
It's more flexible (you can use $target as a sort of default/final assignment variable, with little effort (will add example below if I find the time)
No reference mess and risks to deal with
Example using adaptation of the function above to assign value at "lowest" level:
function addArrayLevels(array $keys, $value)
{
$return = [];
$key = array_shift($keys);
if ($keys) {
$return[$key] = addArrayLevels($keys, $value);
} else {
$return[$key] = $value;
}
return $return;
}
$keys = range(1, 10);
$subArrays = addARrayLevels($keys, 'innerValue');
var_dump($subArrays);
Demo
I don't think that there is built-in function for that but you can do that with simple foreach and references.
$newArray = [];
$keys = ['key1', 'key2', 'key3'];
$reference =& $newArray;
foreach ($keys as $key) {
$reference[$key] = [];
$reference =& $reference[$key];
}
unset($reference);
var_dump($newArray);
I'm trying to remove duplicated entries where value and type are both equal on a multidimensional associative array, but only using recursion and without array_unique. All keys are associative.
I tried this, and I'm getting the same result as the main array. My logic seems to fail me at this late hour.
function rmDuplicates(&$array) {
$uniqueArray = array();
foreach($array as $k=>$v) {
if (is_array($v)) {
$uniqueArray[$k] = rmDuplicates($v);
} else {
if (!in_array($v, $uniqueArray)) {
$uniqueArray[] = $v;
}
}
}
return $uniqueArray;
}
The following code uses a simple strategy for finding the max of the nested array. It uses foreach to find and label the max value, however, if I got an array that was nested to MORE than two levels, than my code would be useless. Can anyone please explain to me the idea of a function calling itself for it to find unlimited nested arrays? Would be much appreciated.
Here is my code for example:
<?php
$arr = array("1", "2", array("3", "4"));
foreach($arr as $value){
if(is_array($value)){
foreach($value as $value2){
$max_array=array($value);
// no deeper levels
}
} else {
$max_array=array($value);
}
}
echo max($max_array);
?>
You can use array_walk_recursive() for it:
function array_max_recursive($arr)
{
$max = -INF;
array_walk_recursive($arr, function($item) use (&$max) {
if ($item > $max) {
$max = $item;
}
});
return $max;
}
echo array_max_recursive(["1", "2", ["3", "4"]]); // 4
What you want is a recursive function.
The function looks up the biggest element in a an array. If an item in the array is an array, it will find the biggest item in that array and use that to compare.
To find the biggest value in that array it will use the same function.
function findMax($arr){
$max = 0;
foreach($arr as $item){
if(is_array($item)){
$val = findMax($item);
}else{
$val = $item;
}
$max = $val>$max?$val:$max;
}
return $max;
}
Use example:
$arr = Array(1,2,Array(3,10,Array(6,7)));
$arr2 = Array(1,2,Array(3,5,Array(6,7)));
echo findMax($arr)."\n".findMax($arr2);
Result:
10
7