I have a large while loop function, every time it gets loaded for check with current URL name.
So I need to know which one is better to check the URL name in large array within the while loop,
in_array() or array_search() function.
If it's a large array and in a loop, neither is "best". Instead use array_flip() on your array, so urls become keys. And use isset() to check for the presence.
There's no real answer here. So I tried it, myself.
$haystack = array
(
'apple',
'banana',
'cherry',
'lemon',
'lime',
'orange',
'potato',
'rutabaga'
);
$haySize = count($haystack);
$loops = isset( $_SERVER['argv'][1] ) ? $_SERVER['argv'][1] : 10000;
// echo 'Loops: ' . $loops . "\n";
$start = microtime(true);
for ($i = 0; $i < $loops; $i++)
{
$needle = $haystack[ $i % $haySize ];
}
$zeroTime = microtime(true) - $start;
// echo sprintf('%0.3f', $zeroTime * 1000) . ' ms : zero time' . "\n";
$start = microtime(true);
for ($i = 0; $i < $loops; $i++)
{
$needle = $haystack[ $i % $haySize ];
$dummy = array_search($needle, $haystack);
}
echo sprintf('%0.3f', (microtime(true) - $start - $zeroTime) * 1000) . ' ms : array_search' . "\n";
$start = microtime(true);
for ($i = 0; $i < $loops; $i++)
{
$needle = $haystack[ $i % $haySize ];
$dummy = in_array($needle, $haystack);
}
echo sprintf('%0.3f', (microtime(true) - $start - $zeroTime) * 1000) . ' ms : in_array' . "\n";
echo sprintf('%0.3f', (microtime(true) - $start) * 1000).' ms : in_array'."\n";
For a typical use case, in_array wins, but the difference is negligible:
22.662 ms : array_search
22.104 ms : in_array
Updated 2014-01-02: added noop loop to "zero the scale". Running PHP 5.4.17 on a new MacBook pro, this is a typical result:
24.462 ms : array_search
24.984 ms : in_array
Based on the documentation of in_array and array_search, I'd think that it mainly depends on what you want to do with the information: if you need the entry, use array_search, if you just want to check if the url exists in the array, in_array should be enough.
it's different function
in_array - return true if find value
array_search - return position if find value
$a = array('a', 'b');
var_dump(in_array('a', $a)); // return true
var_dump(array_search('a', $a)); // return 0
if (array_search('a', $a)) - false
If you're only goal is to check if an URL exists in the array I'd go for in_array. Altough the best way is having keys set so you can just search by array key. That way you save alot of looping.
$searchword = "test";
echo $array[$searchword];
It's up to your array-size.
-If you have a small array(like < 500k 32bit-key),
in_array and array_search give you same performance
isset(array[needle]) make no sense because of flip()
-By big arrays(like > 1m 32bit key)
There are really big difference between in_array and isset(array[needle])
array1=array("a"=>"one","b"=>"two");
if(in_array("one",$array))
{
echo "array exit";
}
else
{
echo " array not exist";
}
echo "</br>";
//example of array_search():
$b1=array("a"=>"one","b"=>"two");
echo array_search("one",$b1);
in_array return true and false value and array_search return key of the array
Related
find out minimum number of adjacent swaps require to make the array sorted.
the approach I use is finding a repeated cycle within my array for example 3->1->4->2 is cycle of 4 so minimum swap of 3 with input of [3,1,4,2,5] to make it sorted [1,2,3,4,5]
I have three arrays, $old contains unsorted array, $arr is sorted, and $bool counts whether the position is visited or not
$old = $arr;
quicksort($arr, 0, count($arr) - 1);
$bool = array_fill(0, count($arr), false);
$count = 0;
$circle = 0;
for ($i = 0; $i < count($bool); $i++){
if ($arr[$i] !== $old[$i]) {
$circle ++;
$where = array_search($old[$i], $arr);
$bool[$i] = true;
if ($bool[$where]) {
$count += $circle;
$circle = 0;
}
}
}
return $count;
the idea is skipping element that is already in right index,
and mark element that is not, keeping count of cycle (i used $circle), once a right position is already marked, i conclude that a cycle is reached,
but this logic is not behaving what I expected, need some help.
I think what you are after is something like this, however I might be wrong.
I tried to keep it simple with a lot of loops to make it work, and explained the different steps in the code
<?php
$minSize = 3;
$arr = [3,1,2,6,9,3,5,2,6,9,3,5,1,8,4,6,6,9,3,0];
$repeats = [];
//outer loop
for($i = 0; $i < count($arr); $i++) {
$currValue = $arr[$i];
//get all the keys for where the value is the same as $currValue
//this gives a starting position to test our matching sets
$matches = array_keys($arr, $currValue);
//match loop
for($j = 0; $j < count($matches); $j++) {
$leftIndex = $currValue; //this needs to be reset for every set
$matchIndex = $matches[$j];
//now we do want matches only when the index is different, always it will always match
if($leftIndex === $matchIndex) {
continue;
}
$subsequentMatch = 0;
//isset so we don't go out of bounds of our array
while(isset($arr[$leftIndex], $arr[$matchIndex]) && $arr[$leftIndex] === $arr[$matchIndex]) {
$subsequentMatch++;
$leftIndex++;
$matchIndex++;
}
if($subsequentMatch >= $minSize) {
$repeats[] = array_slice($arr, $currValue, $subsequentMatch) ;
}
}
}
print_r($repeats);
See an example here : https://3v4l.org/cBWQ5
you could improve on this by doing
for($i = 0; $i < (count($arr) - $minSize ); $i++) {
because if the set is under $minSize it will never be added to the repeats
EDIT: based on comments, OP might be looking for this ?
<?php
$arr = [3,1,2,6,9,3,5,2,6,9,3,5,1,8,4,6,6,9,3,0];
$swapCount = 0;
usort($arr, function ($a, $b) use (&$swapCount) {
if($a === $b) {
return 0;
}
$swapCount++;
return $a <=> $b;
});
echo 'Arr Count: ' . count($arr) . PHP_EOL;
echo 'Swaps performed: ' . $swapCount;
This is a simple sort, I suppose you could write a usort and count with each different sort mechanism (the list is endless), and then find out the min value of that
list of sorting mechanism off the top of my head
Insert Sort
Bubble Sort
Quick Sort
Counting Sort
Comb Sort
Heap Sort
Merge Sort
Shell Sort
Odd Even Sort
You can google on how to implement these in PHP, there are probably more ways too.
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 have some troubles with an array. I have one array that I want to modify like below. I want to remove element (elements) of it by index and then re-index array. Is it possible?
$foo = array(
'whatever', // [0]
'foo', // [1]
'bar' // [2]
);
$foo2 = array(
'foo', // [0], before [1]
'bar' // [1], before [2]
);
unset($foo[0]); // remove item at index 0
$foo2 = array_values($foo); // 'reindex' array
array_splice($array, 0, 1);
http://php.net/manual/en/function.array-splice.php
You better use array_shift(). That will return the first element of the array, remove it from the array and re-index the array. All in one efficient method.
array_splice($array, array_search(array_value, $array), 1);
2020 Benchmark in PHP 7.4
For these who are not satisfied with current answers, I did a little benchmark script, anyone can run from CLI.
We are going to compare two solutions:
unset() with array_values() VS array_splice().
<?php
echo 'php v' . phpversion() . "\n";
$itemsOne = [];
$itemsTwo = [];
// populate items array with 100k random strings
for ($i = 0; $i < 100000; $i++) {
$itemsOne[] = $itemsTwo[] = sha1(uniqid(true));
}
$start = microtime(true);
for ($i = 0; $i < 10000; $i++) {
unset($itemsOne[$i]);
$itemsOne = array_values($itemsOne);
}
$end = microtime(true);
echo 'unset & array_values: ' . ($end - $start) . 's' . "\n";
$start = microtime(true);
for ($i = 0; $i < 10000; $i++) {
array_splice($itemsTwo, $i, 1);
}
$end = microtime(true);
echo 'array_splice: ' . ($end - $start) . 's' . "\n";
As you can see the idea is simple:
Create two arrays both with the same 100k items (randomly generated strings)
Remove 10k first items from first array using unset() and array_values() to reindex
Remove 10k first items from second array using array_splice()
Measure time for both methods
Output of the script above on my Dell Latitude i7-6600U 2.60GHz x 4 and 15.5GiB RAM:
php v7.4.8
unset & array_values: 29.089932918549s
array_splice: 17.94264793396s
Verdict: array_splice is almost twice more performant than unset and array_values.
So: array_splice is the winner!
Unset($array[0]);
Sort($array);
I don't know why this is being downvoted, but if anyone has bothered to try it, you will notice that it works.
Using sort on an array reassigns the keys of the the array. The only drawback is it sorts the values.
Since the keys will obviously be reassigned, even with array_values, it does not matter is the values are being sorted or not.
Try with:
$foo2 = array_slice($foo, 1);
After some time I will just copy all array elements (excluding these unwanted) to new array
I need to generate a large list of random numbers from 600k to 2000k, but the
list can not have duplicates.
My current 'implementation' looks like this:
<?php
header('Content-type: text/plain');
$startTime = microtime(true);
$used = array();
for ($i=0; $i < 600000; ) {
$random = mt_rand();
//if (!in_array($random, $used)) {
$used[] = $random;
$i++;
//}
}
$endTime = microtime(true);
$runningTime = $endTime - $startTime;
echo 'Running Time: ' . $runningTime;
//print_r($used);
?>
If I keep the in_array test commented the processing time is around 1 second, so
the mt_rand calls and the used array filling are relatively 'cheap' but when I uncomment
the in_array test bad things happens! (I'm just waiting -it's been more then 10 minutes- for the script to terminate...)
So I'm looking for alternatives either on the duplicate detection side or in the generation part (How could i generate random numbers without the risk of getting duplicates)
I'm open to any suggestion.
For a quick/dirty solution, does using/checking array keys improve your speed at all?
$used = array();
for ($i = 0; $i < 600000; ) {
$random = mt_rand();
if (!isset($used[$random])) {
$used[$random] = $random;
$i++;
}
}
$used = array_values($used);
in_array requires to search the whole array in the worst case, that means linear costs (O(n)). But using the array key as – well – the key, the costs are constant (O(1)) since the costs for array access is always constant.
You could for example do something like this instead
$random = mt_rand();
$array = range($random, $random + 600000);
$array = shuffle($array);
That would create a array that first is in order, but then it shuffles the array, so the values will be random. No collisions! :D
If you do the looping anyways and if you don't need more than 600000 why would you check them at all, why not just append $i to $random. done. not random enough?
for ($i = 0; $i < 600000; $i++)
{
$yourArray[] = mt_rand() . $i;
}
Furthermore there is the array function array_unique, which removes duplicate values from an array.
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);