Say I have an array like this:
$array = array('', '', 'other', '', 'other');
How can I count the number with a given value (in the example blank)?
And do it efficiently? (for about a dozen arrays with hundreds of elements each)
This example times out (over 30 sec):
function without($array) {
$counter = 0;
for($i = 0, $e = count($array); $i < $e; $i++) {
if(empty($array[$i])) {
$counter += 1;
}
}
return $counter;
}
In this case the number of blank elements is 3.
How about using array_count _values to get an array with everything counted for you?
Just an idea, you could use array_keys( $myArray, "" ) using the optional second parameter which specifies a search-value. Then count the result.
$myArray = array( "","","other","","other" );
$length = count( array_keys( $myArray, "" ));
I dont know if this would be faster but it's something to try:
$counter = 0;
foreach($array as $value)
{
if($value === '')
$counter++;
}
echo $counter;
You could also try array_reduce, with a function which would just count the value you are interested in. eg
function is_empty( $v, $w )
{ return empty( $w ) ? ($v + 1) : $v; }
array_reduce( $array, 'is_empty', 0 );
Some benchmarking might tell you if this is faster than array_count_values()
We use array_filter function to find out number of values in array
$array=array('','','other','','other');
$filled_array=array_filter($array);// will return only filled values
$count=count($filled_array);
echo $count;// returns array count
Generally for counting blanks only.
Really depends on use case and speed needed. Personally I like doing things one one line.
Like the chosen response though But you still need a line to extract the data needed though to another variable.
$r = count($x) - count(array_filter($x));
function arrayvaluecount($array) {
$counter = 0;
foreach($array as $val){
list($v)=$val;
if($v){
$counter =$counter+1;
}
}
return $counter;
}
function countarray($array)
{ $count=count($array);
return $count;
}
$test=$array = array('', '', 'other', '', 'other');
echo countarray($test);
Related
Say I have an array like this:
$array = array('', '', 'other', '', 'other');
How can I count the number with a given value (in the example blank)?
And do it efficiently? (for about a dozen arrays with hundreds of elements each)
This example times out (over 30 sec):
function without($array) {
$counter = 0;
for($i = 0, $e = count($array); $i < $e; $i++) {
if(empty($array[$i])) {
$counter += 1;
}
}
return $counter;
}
In this case the number of blank elements is 3.
How about using array_count _values to get an array with everything counted for you?
Just an idea, you could use array_keys( $myArray, "" ) using the optional second parameter which specifies a search-value. Then count the result.
$myArray = array( "","","other","","other" );
$length = count( array_keys( $myArray, "" ));
I dont know if this would be faster but it's something to try:
$counter = 0;
foreach($array as $value)
{
if($value === '')
$counter++;
}
echo $counter;
You could also try array_reduce, with a function which would just count the value you are interested in. eg
function is_empty( $v, $w )
{ return empty( $w ) ? ($v + 1) : $v; }
array_reduce( $array, 'is_empty', 0 );
Some benchmarking might tell you if this is faster than array_count_values()
We use array_filter function to find out number of values in array
$array=array('','','other','','other');
$filled_array=array_filter($array);// will return only filled values
$count=count($filled_array);
echo $count;// returns array count
Generally for counting blanks only.
Really depends on use case and speed needed. Personally I like doing things one one line.
Like the chosen response though But you still need a line to extract the data needed though to another variable.
$r = count($x) - count(array_filter($x));
function arrayvaluecount($array) {
$counter = 0;
foreach($array as $val){
list($v)=$val;
if($v){
$counter =$counter+1;
}
}
return $counter;
}
function countarray($array)
{ $count=count($array);
return $count;
}
$test=$array = array('', '', 'other', '', 'other');
echo countarray($test);
I need to calculate the average increase of array values, and I've made a little script which works, but I'd like to know if:
There is a better, more efficient way of doing this
My logic is correct here in calculating the average increase
Lets say I have an array like so:
$array = array(5,10,15,10,0,15);
Lets also imagine that each array item is 1 day, and the value is some counter for that day. I would like to calculate the average increase/decrease in the counter.
What I've done, is looped through the array, and altered the values so that the current item = current item - previous item, what way I'm left with an array which would look like so:
$array = array(5,5,-5,-10,15);
Then I calculate the average as per normal, which in this example would give me a 2 average increase on a daily basis.
Code here:
$array = array(5,10,15,10,0,15);
$count = count($array);
for($i=0;$i<$count;$i++) {
if($i==0) {
$value = $array[$i];
unset($array[$i]);
}
else {
$tmp = $array[$i];
$array[$i] -= $value;
$value = $tmp;
}
}
echo array_sum($array) / count($array);
Is the logic correct here, and is there a more efficient way of doing this, maybe without the loop?
Thanks in advance :)
EDIT: Updated code to account for excluding first value
How about this:
function moving_average($array) {
for ($i = 1; $i < sizeof($array); $i++) {
$result[] = $array[$i] - $array[$i-1];
}
return array_sum($result)/count($result);
}
Try this :
$array = array(5,10,15,10,0,15);
$array2 = $array;
array_pop($array2);
array_unshift($array2, $array[0]);
$subtracted = array_map(function ($x, $y) { return $y-$x; } , $array2, $array);
array_shift($subtracted); /// Comment this if you want six values with 0 as first value
echo array_sum($subtracted) / count($subtracted);
Here's a snazzy one-liner for you:
$days = array(5, 10, 15, 10, 0, 15);
$deltas = array_slice(array_map(function($day1, $day2) {
return $day2 - $day1;
}, $days, array_slice($days, 1)), 0, -1);
var_dump(array_sum($deltas) / count($deltas));
$array = array(5,10,15,10,0,15);
list($prevVal) = array_slice($array, 1);
array_walk($array, function($value, $key, &$prevVal) use(&$array){
if ($key==0) { return; }
$array[$key] = ($value - $prevVal);
$prevVal = $value;
}, $prevVal);
echo array_sum($array) / count($array);
Outputs 1.6666666666667 in float(3.0994415283203E-5)
I want to generate test data for testing. What I need:
I will have a list of 30 names. For each name I need to fill in the start and finish position. The position is between 1 and 30.
So I wanted to use RAND() in php but I have a problem what I can't find a good way for.
Every position can only be used once. So if I press on a button "generate data" I want for all 30 names a start and finish position without duplicate position. So in the start i will use 1 - 30 and for the finish 1 - 30 as well.
I need this data in textfield. Is there a simple function for this? Or do you know how I can do this without having to fill in 60 textfields every test.
Something like this might get you started:
$names = array(/*...*/);
$l = count($names);
$rand = array();
for ($i = 0; $i<$l; $i++) {
$rand[] = $i;
}
shuffle($rand);
for ($i = 0; $i < $l; $i++) {
$names[$i]['start'] = $rand[$i];
}
Or:
$names = array(/*...*/);
shuffle($names);
for ($i = 0, $l = count($names); $i < $l; $i++) {
$names[$i]['start'] = $i;
}
I will use shuffle (twice),
something like
$arr = range(1, 30);
$first_numbers_position = shuffle($arr);
$second_numbers_position = shuffle($arr);
if you have already array with the names
you can use this function
Very simple shuffle function preserving key with value
function shuffle_assoc( $array )
{
$keys = array_keys( $array );
shuffle( $keys );
return array_merge( array_flip( $keys ) , $array );
}
If you don't need your code to actually generate the data dynamically you could try something like this site http://www.generatedata.com/
If I have a PHP array:
$array
With values:
45,41,40,39,37,31
And I have a variable:
$number = 38;
How can I return the value?:
39
Because that is the closest value to 38 (counting up) in the array?
Regards,
taylor
<?php
function closest($array, $number) {
sort($array);
foreach ($array as $a) {
if ($a >= $number) return $a;
}
return end($array); // or return NULL;
}
?>
Here is a high-level process to get the desired results and work for any array data:
Filter the array keeping on values greater than or equal to the target and then select the lowest remaining value. This is the "best" value (which may be "nothing" if all the values were less) -- this is O(n)
Alternatively, sort the data first and see below -- this is O(n lg n) (hopefully)
Now, assuming that the array is sorted ASCENDING, this approach would work:
Loop through the array and find the first element which is larger than or equal to the target -- this is O(n)
And if the array is DESCENDING (as in the post), do as above, but either:
Iterate backwards -- this is O(n)
Sort it ASCENDING first (see fardjad's answer) -- this is O(n lg n) (hopefully)
Iterate forwards but keep a look-behind value (to remember "next highest" if the exact was skipped) -- this is O(n)
Happy coding.
EDIT typo on array_search
Yo... Seems easy enough. Here's a function
<?php
$array = array(45,41,40,39,37,31);
function closest($array, $number){
#does the array already contain the number?
if($i = array_search( $number, $array)) return $i;
#add the number to the array
$array[] = $number;
#sort and refind the number
sort($array);
$i = array_search($number, $array);
#check if there is a number above it
if($i && isset($array[$i+1])) return $array[$i+1];
//alternatively you could return the number itself here, or below it depending on your requirements
return null;
}
to Run echo closest($array, 38);
Here's a smaller function that will also return the closest value. Helpful if you don't want to sort the array (to preserve keys).
function closest($array, $number) {
//does an exact match exist?
if ($i=array_search($number, $array)) return $i;
//find closest
foreach ($array as $match) {
$diff = abs($number-$match); //get absolute value of difference
if (!isset($closeness) || (isset($closeness) && $closeness>$diff)) {
$closeness = $diff;
$closest = $match;
}
}
return $closest;
}
Do a linear scan of each number and update two variables and you'll be done.
Python code (performance is O(N), I don't think it's possible to beat O(N)):
def closestNum(numArray, findNum):
diff = infinity # replace with actual infinity value
closestNum = infinity # can be set to any value
for num in numArray:
if((num - findNum) > 0 and (num - findNum) < diff):
diff = num - findNum
closestNum = num
return closestNum
Please add null checks as appropriate.
If you really want the value that's "closest" in distance, even if it's a lesser value, try this, which #Jason gets most of the credit for.
Imagine a scenario when you want the closest number to 38.9 in the following:
$array = array(37.5, 38.5, 39.5);
Most of the solutions here would give you 39.5, when 38.5 is much closer.
This solution would only take the next highest value if what you're looking is in the exact middle between two numbers in the array:
function nearest_value($value, $array) {
if (array_search($value, $array)) {
return $value;
} else {
$array[] = $value;
sort($array);
$key = array_search($value, $array);
if ($key == 0) { return $array[$key+1]; }
if ($key == sizeof($array)-1) { return $array[$key-1]; }
$dist_to_ceil = $array[$key+1]-$value;
$dist_to_floor = $value-$array[$key-1];
if ($dist_to_ceil <= $dist_to_floor) {
return $array[$key+1];
} else {
return $array[$key-1];
}
}
}
What it lacks in elegance, it makes up for in accuracy. Again, much thanks to #Jason.
Try this simple PHP function:
<?php
function nearest($number, $numbers) {
$output = FALSE;
$number = intval($number);
if (is_array($numbers) && count($numbers) >= 1) {
$NDat = array();
foreach ($numbers as $n)
$NDat[abs($number - $n)] = $n;
ksort($NDat);
$NDat = array_values($NDat);
$output = $NDat[0];
}
return $output;
}
echo nearest(90, array(0, 50, 89, 150, 200, 250));
?>
I made a shorter function for that:
function nearestNumber($num, $array) {
if(!in_array($num, $array)) $array[] = $num;
sort($array);
$idx = array_search($num, $array);
if(($array[$idx] -$array[$idx-1]) >= ($array[$idx+1] -$array[$idx])) return $array[$idx+1];
else return $array[$idx-1];
}
Works great in my case: $array = array(128,160,192,224,256,320); $num = 203 :)
It's taking the nearest number and if there's the same distance between two numbers (like 208 for my example), the next highest number is used.
+1 to Jason.
My implementation below, but not as brisk
$array = array(1,2,4,5,7,8,9);
function closest($array, $number) {
$array = array_flip($array);
if(array_key_exists($number, $array)) return $number;
$array[$number] = true;
sort($array);
$rendered = array_slice($array, $number, 2, true);
$rendered = array_keys($rendered);
if(array_key_exists(1, $rendered)) return $rendered[1];
return false;
}
print_r(closest($array, 3));
You could use array_reduce for this, which makes it more functional programming style:
function closest($needle, $haystack) {
return array_reduce($haystack, function($a, $b) use ($needle) {
return abs($needle-$a) < abs($needle-$b) ? $a : $b;
});
}
For the rest, this follows the same principle as the other O(n) solutions.
Here is my solution.
$array=array(10,56,78,17,30);
$num=65;
$diff=$num;
$min=$num;
foreach($array as $a){
if( abs($a-$num)< $diff ){
$diff=abs($a-$num);
$min=$a;
}
}
echo $min;
I have an associative array, ie
$primes = array(
2=>2,
3=>3,
5=>5,
7=>7,
11=>11,
13=>13,
17=>17,
// ...etc
);
then I do
// seek to first prime greater than 10000
reset($primes);
while(next($primes) < 10000) {}
prev($primes);
// iterate until target found
while($p = next($primes)) {
$res = doSomeCalculationsOn($p);
if( IsPrime($res) )
return $p;
}
The problem is that IsPrime also loops through the $primes array,
function IsPrime($num) {
global $primesto, $primes, $lastprime;
if ($primesto >= $num)
// using the assoc array lets me do this as a lookup
return isset($primes[$num]);
$root = (int) sqrt($num);
if ($primesto < $root)
CalcPrimesTo($root);
foreach($primes as $p) { // <- Danger, Will Robinson!
if( $num % $p == 0 )
return false;
if ($p >= $root)
break;
}
return true;
}
which trashes the array pointer I am iterating on.
I would like to be able to save and restore the array's internal pointer in the IsPrime() function so it doesn't have this side effect. Is there any way to do this?
You can "save" the state of the array:
$state = key($array);
And "restore" (not sure if there's a better method):
reset($array);
while(key($array) != $state)
next($array);
Don't rely on array pointers. Use iterators instead.
You can replace your outer code with:
foreach ($primes as $p) {
if ($p > 10000 && IsPrime(doSomeCalculationsOn($p))) {
return $p;
}
}
If speed is not an issue and you aren't pushing php memory limits the quickest solution is just to duplicate your primes array and iterate 2 different ones.
$awesomePrimes=$primes;
Then change globals and foreach in your function to $awesomePrimes
How about doing one more array of int -> int, where the the index is a running number from 0 to n and the value is the index of the associative array? So, you would have:
$pointer = array(
0 => 2,
1 => 3,
2 => 5,
// ...
);
and instead of referring directly to $prime you would use $prime[$pointer[$i]], or something similar?
use a "for" loop for one of your iterations. for example use this loop in your IsPrime method:
$primesLength = count($primes); // this is to avoid calling of count() so many times.
for ($counter=0 ; $counter < $primesLength ; $counter++) {
$p = $primesLength[$counter];
if( $num % $p == 0 )
return false;
if ($p >= $root)
break;
}
this way the internal array pointer will not be used in the method.