Related
I need to find the min and max position into an array where some value exist!
use a loop inside a loop to compare values is not an option ( my array has 100.000 values )
e.g=
$myarray[0]="red";
$myarray[1]="red";
$myarray[2]="blue";
$myarray[3]="blue";
$myarray[4]="blue";
$myarray[5]="red";
how to get the min and max position where blue exist?
Use the second argument for array_keys:
if($blue = array_keys($myarray, 'blue')) {
$min = min($blue);
$max = max($blue);
}
may be this is the answer?
function getMinKey($arr, $search){
if(!in_array($search, $arr)){
return false;
}
foreach($arr as $key => $value){
if($value == $search){
return $key;
}
}
}
function getMaxKey($arr, $search){
if(!in_array($search, $arr)){
return false;
}
$arrCount = count($arr)-1;
for($i = $arrCount; $i >=0; $i--){
if($arr[$i] == $search){
return $i;
}
}
}
All solutions, so far, have searched the whole array, which might be quite inefficient. You only need to search from the start upto the first "blue" and from the end downto the last "blue". Like this:
$find = "blue";
$first = false;
$last = false;
$max = count($myarray);
$key = 0;
while ($key < $max) {
if ($myarray[$key] == $find) {
$first = $key;
break;
}
$key++;
}
if ($first !== false) {
$key = --$max;
while ($key > 0) {
if ($myarray[$key] == $find) {
$last = $key;
break;
}
$key--;
}
}
Note that this code takes into account that nothing will be found. In that case $first and $last will contain false. It also checks to see if the $first was found to prevent searching through the array twice when there's clearly no need for that.
You can use array_keys with the search_value to extract all the matching keys, and then max and min to get the two ones that you want.
$keys = array_keys($myarray,'blue'); //[2,3,4]
$maxKey = max($keys); //4
$minKey = min($keys); //2
I have to advise that performance wise is better to do a for loop:
$length = count($myarray);
$minKey = FALSE;
$maxKey = FALSE;
$search = 'blue';
for($i=0;$i<$length;$i++){
if($myarray[$i] == $search){
if($minKey === FALSE) $minKey = $i;
$maxKey = $i;
}
}
Given an array a that contains only numbers in the range from 1 to a.length, find the first duplicate number for which the second occurrence has the minimal index. In other words, if there are more than 1 duplicated numbers, return the number for which the second occurrence has a smaller index than the second occurrence of the other number does. If there are no such elements, return -1.
My code:
function firstDuplicate($a) {
$unique = array_unique($a);
foreach ($a as $key => $val) {
if ($unique[$key] !== $val){
return $key;
}else{
return -1;
}
}
}
The code above will be OK when the input is [2, 4, 3, 5, 1] but if the input is [2, 1, 3, 5, 3, 2] the output is wrong. The second duplicate occurrence has a smaller index. The expected output should be 3.
How can I fix my code to output the correct result?
$arr = array(2,1,3,5,3,2);
function firstDuplicate($a) {
$res = -1;
for ($i = count($a); $i >= 1; --$i) {
for ($j = 0; $j < $i; ++$j) {
if ($a[$j] === $a[$i]) {
$res = $a[$j];
}
}
}
return $res;
}
var_dump(firstDuplicate($arr));
By traversing the array backwards, you will overwrite any previous duplicates with the new, lower-indexed one.
Note: this returns the value (not index), unless no duplicate is found. In that case, it returns -1.
// Return index of first found duplicate value in array
function firstDuplicate($a) {
$c_array = array_count_values($a);
foreach($c_array as $value=>$times)
{
if($times>1)
{
return array_search($value, $array);
}
}
return -1;
}
array_count_values() will count the duplicate values in the array for you then you just iterate over that until you find the first result with more then 1 and search for the first key in the original array matching that value.
Python3 Solution:
def firstDuplicate(a):
mySet = set()
for i in range(len(a)):
if a[i] in mySet:
return a[i]
else:
mySet.add(a[i])
return -1
function firstDuplicate($a) {
foreach($a as $index => $value) {
$detector[] = $value;
$counter = 0;
foreach($detector as $item) {
if($item == $value) {
$counter++;
if($counter >= 2) {
return $value;
break;
}
}
}
}
return -1;
}
It's easy to just get the first number that will be checked as duplicated, but unfortunately, this function exceeded 4 seconds with a large array of data, so please using it with a small scale of array data.
EDIT
I have new own code fixes execution time for large array data
function firstDuplicate($a) {
$b = [];
$counts = array_count_values($a);
foreach($counts as $num => $duplication) {
if($duplication > 1) {
$b[] = $num;
}
}
foreach($a as $value) {
if(in_array($value, $b)) {
$detector[] = $value;
$counter = 0;
foreach($detector as $item) {
if($item == $value) {
$counter++;
if($counter >= 2) {
return $value;
break;
}
}
}
}
}
return -1;
}
The new code target the current numbers having a reputation only by using array_count_values()
function firstDuplicate($a) {
$indexNumber = -1;
for($i = count($a); $i >= 1 ; --$i){
for($k = 0; $k < $i; $k++){
if(isset($a[$i]) && ($a[$i] === $a[$k]) ){
$indexNumber = $a[$k];
}
}
}
return $indexNumber;
}
Remove error from undefined index array.
can anyone help me with this following Array sorting
Input
$array=array(1,2,3,6,7,8,100,101,200);
Output:
$new_array=array(
0=>array(1,2,3),
1=>array(6,7,8),
2=>array(100,101),
3=>array(200)
);
Thanks in advance!
$array=array(1,2,3,6,7,8,100,101,200);
$new_array = array();
$lastNumber = '';
foreach($array as $number) {
if($lastNumber === '') {
$otherArray = array($number);
}
elseif($lastNumber + 1 !== $number) {
$new_array[] = $otherArray;
$otherArray = array($number);
}
else{
$otherArray[] = $number;
}
$lastNumber = $number;
}
$new_array[] = $otherArray;
print_r($new_array);
You can loop over the array and check the distance to the next element in the array. If this distance is larger then one add a new sub array:
$array=array(1,2,3,6,7,8,100,101,200);
$result=array(array());
for($i=0; $i<count($array)-1; $i++)
{
if($array[$i+1]-$array[$i]==1)
{
// If difference to next number is one -> push
array_push($result[count($result)-1], $array[$i]);
}
else
{
// ... else: Push and create new array for the next element
array_push($result[count($result)-1], $array[$i]);
array_push($result, array());
}
}
// Push the last number
array_push($result[count($result)-1], $array[$i]);
print_r($result);
Just a different approach with array_push()...
Pretty simple: loop through the numbers, remember the last one, if the current number is not the successor of the last one, add a new array to your result, push into the last array in your result.
$result = [];
$last = null;
foreach ($array as $number) {
if ($last !== $number - 1) {
$result[] = [];
}
$result[count($result) - 1][] = $number;
$last = $number;
}
You could even get rid of $last and directly read the last array element of the last array element of $result, but that would make the code actually more complicated.
I need to find not just duplicates in an array, but numbers that are within 1 of each other.
example: $myArr = array(46,78,77,43,86,1,47,14,51,31)
How would I get find those numbers if there no duplicates were found?
Thanks.
This will work - tested:
$myArr = array(46,78,77,43,86,1,47,14,51,31);
$i = 1;
while($i <= 99){
if(in_array($i, $myArr)){
// This means it's in the array
// Let's see if it's +1 of the last #
if(isset($last_num)){
$res = ($i + 1);
if(in_array($res, $myArr)){
echo $res . ' is in the array<br>';
}
}
}
$last_num = $i;
$i++;
}
Could use something like this.
<?
$haystack = array(31,46,78,77,43,86,1,47,14,51,31);
array_walk($haystack, function($key, $value) use ($haystack) {
$needle = array($key - 1, $key, $key + 1);
$r = array_intersect($haystack, $needle);
if(count($r) > 1) { unset($r[$value]); print_r(array_values($r)); }
});
?>
Or if you want them returned in an array:
<?
$haystack = array(31,46,78,77,43,86,1,47,14,51,31);
$result = array_filter(array_map(function($key, $value) use ($haystack) {
$needle = array($key - 1, $key, $key + 1);
$r = array_intersect($haystack, $needle);
if(count($r) > 1) { unset($r[$value]); return array_values($r)['0']; }
}, $haystack));
print_r($result);
?>
A little more verbose, but it may be more efficient since we're only looping through the array when necessary. It will return the keys of the original array where duplicates and values within range are found. (Note: I've expanded the code out a lot more than I normally would just for readability for OP)
/**
* Find the any values within an array that are within
* the specified range from another value.
*
* #param Array Array to search in
* #param uint Unsigned integer used for comparison
* #return Array The keys of all found values
**/
function findWithinRange(Array $array, $range) {
// sort the array values numerically
// so we don't have to loop through
// the entire array for each check
asort($array, SORT_NUMERIC);
// Keep the keys in case it's an associative array
$keys = array_keys($array);
// Get the values without the keys so we can easily loop
$values = array_values($array);
$return = array();
// Loop over each item in the array
foreach( $values as $k => $v ) {
$start = $k;
$min = $v - $range;
$max = $v + $range;
// track backwards in the array until we're less than range
// We could use array_search, but we'd be calling it multiple times
// This only runs through the array once and dies the moment
// it is out of the specified range
while(true) {
$k--;
if( !isset($values[$k]) ) {
break; // don't continue if we run out of keys
}
$curVal = $values[$k];
if( $curVal >= $min ) {
$return[] = $keys[$k];
}
else {
break; // kill the while loop if we're outside of range
}
}
// reset
$k = $start;
// track forward in the array until we're greater than range
while(true) {
$k++;
if( !isset($values[$k]) ) {
break; // don't continue if we run out of keys
}
$curVal = $values[$k];
if( $curVal <= $max ) {
$return[] = $keys[$k];
}
else {
break; // kill the while loop if we're outside of range
}
}
}
// drop duplicate reports
$return = array_unique($return);
// return all found keys
return $return;
}
Example usage:
$myArr = array(46,78,77,43,86,1,47,14,51,31);
$res = findWithinRange($myArr, 1);
var_export($res);
// array(6, 0, 1, 2)
I would like to find the second highest variable in an array.
For example if I have:
$cookies = array(
"chocolate" => "20",
"vanilla" => "14",
"strawberry" => "18",
"raspberry" => "19",
"bluebery" => "29"
);
I can use max($cookies) to find the highest variable, which is "bluebery" => "29".
But how do I find the second highest? "chocolate" => "20"
Sort it and get the second item is the easiest way:
arsort($cookies);
$keys = array_keys($cookies);
echo $keys[1]; // chocolate
echo $cookies[$keys[1]]; // 20
If you want a more efficient way, you can also do it manually, by keeping track of both the highest and second-highest items at the same time:
function secondMax($arr) {
$max = $second = 0;
$maxKey = $secondKey = null;
foreach($arr as $key => $value) {
if($value > $max) {
$second = $max;
$secondKey = $maxKey;
$max = $value;
$maxKey = $key;
} elseif($value > $second) {
$second = $value;
$secondKey = $key;
}
}
return array($secondKey, $second);
}
Usage:
$second = secondMax($cookies);
echo "{$second[0]} => {$second[1]}"; // chocolate => 20
For fun you could use max() twice :)
For example:
Duplicate the array
Run max()
Remove the max
Run max() again
The alternative would to sort the array based on values and get the second element of the array. I'd be curious which is faster. Likely the sort.
arsort($cookies) AND array_shift($cookies) AND list($k, $v) = each($cookies);
echo "$k => $v"; // chocolate => 20
rsort($cookies);
echo $cookies[1];
Try :
asort($cookies);
end($cookies);
prev($cookies);
list($key,$value) = each($cookies);
or reverse it
arsort($cookies);
reset($cookies);
next($cookies);
list($key,$value) = each($cookies);
** Edit **
I thought I'd share this anyway, if someone would stumble across this and need it :
/**
* Returns the key => value pair with the specific rank.
* if $rank is 0, falase is returned. If $rank is positive,
* then the $rank th smallest pair is returned. If $rank
* is negative, then the $rank th biggest pair is returned.
* If $rank range is outside the size of the array, false
* is returned. If a callable function is provided, it will
* be used to sort the data. If $keySort is true, then the
* data will be sorted by keys instead (the callback functions
* will receive the keys to compare instead of values)
*
* #param $data array
* #param $rank int
* #param $cmd_function callable (optional)
* #param $keySort boolean (optional)
* #return array the key => value pair or false
*/
function findByRank($data, $rank, $cmd_function = null, $keySort = false) {
if (($rank == 0) || (abs($rank) > count($data))) {
return false;
}
$sort = ($keySort?'k':'a').'sort';
if ($cmd_function != null) {
$sort = 'u'.$sort;
$sort($data, $cmd_function);
} else {
$sort($data);
}
if ($rank > 0) {
reset($data);
$next = 'next';
} else {
end($data);
$next = 'prev';
$rank = abs($rank);
}
while (--$rank > 0) $next($data);
return each($data);
}
$cookies = array(
"chocolate" => "20",
"vanilla" => "14",
"strawberry" => "18",
"raspberry" => "19",
"bluebery" => "29"
);
header('Content-type:text/plain; charset=utf-8');
var_dump(findByRank($cookies, -10)); // -> false
var_dump(findByRank($cookies, -2)); // -> 'chocolate' key=>value pair
var_dump(findByRank($cookies, -1)); // -> 'blueberry' key=>value pair
var_dump(findByRank($cookies, 0)); // -> false
var_dump(findByRank($cookies, 1)); // -> 'vanilla' key=>value pair
var_dump(findByRank($cookies, 3)); // -> 'raspberry' key=>value pair
Sort the array descending and take the second value. Or, to be save, take the first value and go through the array until you find a smaller one.
function second_largest($arr)
{
sort($arr, SORT_NUMERIC);
return($arr[count($arr) - 2]);
}
//echo 3
echo second_largest(array(0, 3, 4, 1, 2));
Check this URL
http://maheshbokkisam.blogspot.in/2013/04/find-nth-highest-value-in-array-without.html
Find Nth/ N th highest value from given array without using any sorting in PHP
$ar = array(23,56,87,12,98,85,24,54,99,100,1,4,5,2,76,37,92);
$n = count($ar) - 5;
for($i = 0; $i < $n; $i++){
// Get the max value from array // get the Nth value from last loop
echo $a = max($ar);
echo "<br /><pre>"; print_r($ar);
$ar = array_flip($ar); // Flip the array
//print_r($ar);
unset($ar[$a]); // Unset the max value from array
//print_r($ar);
$ar = array_flip($ar); // Flip the array
echo "</pre>";
echo "<hr />";
}
<?php
// Finding Second highest number (In case of index of array is random)
$arr = [-5 => 33, -4 => -2, 8 => 0, 44, 44, 44, 44, 44];
$max = -INF;
$secondMax = -INF;
$size = sizeof($arr);
if ($size > 1) {
foreach ($arr as $key => $value) {
echo "KEY-> ", $key, "VALUE->", $value, "\n";
if ($value > $max) {
$max = $value;
} else {
if ($value < $max && $value > $secondMax) {
$secondMax = $value;
}
}
}
} else if ($size == 0) {
$max = "No Max element";
$secondMax = "No Second highest element";
} else {
foreach ($arr as $key => $value) {
$max = $arr[$key];
$secondMax = "No second highest element";
}
}
echo "maxvalue = ", $max, "\n";
echo "secondmax =", $secondMax;