Related
I have multidimensional array and me need to get a minimum value.
Array may be [65,4,4,511,5,[[54,54[.[.[..].].]] and so on.
example code
<?php
$arr = [5, 1 , 2, 3, [1,5,59,47,58,[0,12,562]]];
function NumMin($arr)
{
$num = '';
foreach ($arr as $item => $i) {
if(is_array($i)){
NumMin($i);
}
else{
$num .= $i.',';
}
}
$num .= $num;
return $num;
}
$g = NumMin($arr);
var_dump($g);
I need to get 0
You can use array_walk_recursive() function to flatten a given array (makes it one-dimensional).
And use simply min() function for getting the desired output after.
array_walk_recursive($arr, function($v) use (&$res){
$res[]=$v;
});
echo min($res);
Demo
<?php
$GLOBALS["min"] = 999999; //min value int
$arr = [[[5,6],7],9,7,5, 1 , 2, 3, [1,5,59,47,58,[1,12,562]]];
array_walk_recursive($arr, 'NumMin');
function NumMin($item)
{
if(intval($item) <= intval($GLOBALS["min"]))
{
$GLOBALS["min"] = intval($item);
}
}
// The end, $GLOBALS["min"] will have the least value
echo $GLOBALS["min"];
?>
The array given has duplicate elements, So basically, I want to find the index of the last occurrence of the element I've searched.
$arr = array(2, 3, 4, 4, 5, 6, 4, 8);
$x = 4; // number to search
$low = 0;
$high = count($arr)-1;
// I want this function to return 6 which is the index of the last occurrence of 4, but instead I'm getting -1 .
function binary_search_last_occ($arr, $x, $low, $high)
{
while ($low <=$high)
{
$mid = floor(($low+$high)/2);
$result = -1;
if ($arr[$mid] == $x)
{
// we want to find last occurrence, so go for
// elements on the right side of the mid
$result = $mid;
$low = $mid+1;
}
else if($arr[$mid] > $x)
{
$high = $mid-1;
}
else
$low = $mid+1;
}
return $result;
}
echo binary_search_last_occ($arr, $x, $low, $high); // outputs -1 ?
I'm not sure, why I'm getting -1. Any suggestions?
I didn't seen your loop but I think this'll really simple to use to gain such functionality
$arr = array(2, 3, 4, 4, 5, 6, 4, 8);
$result = [];
foreach($arr as $key => $val){
$result[$val][] = $key;
}
echo end($result[4]);//6
Or you can simply use the asort function along with array_search like as
$arr = array(2, 3, 4, 4, 5, 6, 4, 8);
asort($arr);
echo array_search(4,$arr);//6
First of all for binary search your array must be sorted, if your array is not sorted you can use simple method like
function binary_search_last_occ($arr, $x, $low, $high)
{
$last_occ = -1;
while ($low <=$high)
{
if($arr[$low] == $x)
$last_occ = $low;
$low++;
}
return $last_occ ;
}
And also define $result above while() to avoid overriding every time with -1. Hence you get the result as -1.
$result = -1;
while ($low <=$high)
{
$mid = floor(($low+$high)/2);
if ($arr[$mid] == $x)
{
// we want to find last occurrence, so go for
// elements on the right side of the mid
$result = $mid;
$low = $mid+1;
}
else if($arr[$mid] > $x)
{
$high = $mid-1;
}
else
$low = $mid+1;
}
return $result;
I want to merge / mix two arrays together, but I want it to be randomly "mixed" however NOT shuffled. For example:
$first = [1, 2, 3, 4];
$second = [10, 20, 30, 40];
Possible desired "mixes" are:
[1, 10, 20, 30, 2, 40, 3, 4]
[10, 1, 2, 20, 30, 3, 4, 40]
[1, 2, 3, 10, 20, 4, 30, 40]
Note that if we pluck the values back out we would still have the original orders of:
1, 2, 3, 4
10, 20, 30, 40
Well, there's (yet another) one possible approach:
$arr = call_user_func_array('array_merge', array_map(null, $first, $second));
print_r($arr); // [1, 10, 2, 20, 3, 30, 4, 40];
Demo. That's apparently deterministic; for random ordering each pair should be shuffled additionally. For example:
function zipShuffle($first, $second) {
return call_user_func_array('array_merge', array_map(function($a, $b) {
return mt_rand(0, 1) ? [$a, $b] : [$b, $a];
}, $first, $second));
}
... but that obviously won't be able to churn out something like [1,2,3,10,20...]. If this is required, here's another solution:
function orderedShuffle($first, $second) {
$results = [];
$stor = [$first, $second];
$i = mt_rand(0, 1);
// switching between arrays on the fly
while (list(, $v) = each($stor[$i])) {
$results[] = $v;
$i = mt_rand(0, 1);
}
// one array is gone, now we need to add all the elements
// of the other one (as its counter left where it was)
$i = 1 - $i;
while (list(, $v) = each($stor[$i])) {
$results[] = $v;
}
return $results;
}
Demo. The last function is actually quite easy to extend for as many arrays as required.
Can you try this,
<?php
$first = array(1,2,3,4);
$second = array(10,20,30,40);
$arrayMixed=array();
$firstReverse=array_reverse($first);
$secondReverse=array_reverse($second);
$firstReverseCount = count($firstReverse);
$secondReverseCount = count($secondReverse);
foreach($firstReverse as $key=>$val) {
if ($firstReverseCount>0) {
array_push($arrayMixed, array_pop($firstReverse));
if ($secondReverseCount>0) {
array_push($arrayMixed, array_pop($secondReverse));
}
}
}
$ArrayMixeddata = array_merge($arrayMixed, $second);
echo "<pre>";
print_r($ArrayMixeddata);
echo "</pre>";
?>
Not quick ways, but them works.
// with permutations
function combineShuffleOrder($first, $second)
{
// combine into one array with alternation
$firstLen = count($first);
$secondLen = count($second);
$max = max($firstLen, $secondLen);
$result = array();
for($i=0; $i < $max; $i++) {
if ($i < $firstLen)
$result[] = $first[$i];
if ($i < $secondLen)
$result[] = $second[$i];
}
// "shuffle" with permutation
$len = count($result);
for($i=1; $i<$len; $i++) {
if (rand(1, 3) % 2 == 0) {
$tmp = $result[$i-1];
$result[$i-1] = $result[$i];
$result[$i] = $tmp;
$i++; // skip one exchange
}
}
return $result;
}
// with using "shuffle" in subarray
function combineShuffleOrder2($first, $second)
{
// combine into one array with alternation
$firstLen = count($first);
$secondLen = count($second);
$max = max($firstLen, $secondLen);
$result = array();
for($i=0; $i < $max; $i++) {
$sub = array();
if ($i < $firstLen)
$sub[] = $first[$i];
if ($i < $secondLen)
$sub[] = $second[$i];
shuffle($sub);
$result = array_merge($result, $sub);
}
return $result;
}
// with using "shuffle" in subarray if sources arrays are equals by length
function combineShuffleOrder3($first, $second)
{
$max = count($first);
$result = array();
for($i=0; $i < $max; $i++) {
$sub = array(
$first[$i],
$second[$i]
);
shuffle($sub);
$result = array_merge($result, $sub);
}
return $result;
}
$first = array(1,2,3,4);
$second = array(10,20,30,40);
print_r(combineShuffleOrder($first, $second));
print_r(combineShuffleOrder2($first, $second));
print_r(combineShuffleOrder3($first, $second));
I recommend forming a single array of the two input arrays for simpler toggling. Simply loop and consume one element from a randomly selected array and push that selection into the result array. When the pool of arrays is reduced to a single array, kill the loop and append the remaining elements of the last surviving array onto the result array.
I'll use a pool of four arrays (one which is empty from the beginning) to demonstrate that the snippet is robust enough to handle a variable number of arrays, a variable number of elements in each array, and empty arrays.
Code: (Demo)
$first = [1, 2, 3, 4];
$second = [10, 20, 30, 40];
$third = [];
$fourth = ['a', 'b'];
$pool = [$first, $second, $third, $fourth];
$result = [];
while (count($pool) > 1) {
$pullFrom = array_rand($pool);
if (!$pool[$pullFrom]) {
unset($pool[$pullFrom]);
continue;
}
$result[] = array_shift($pool[$pullFrom]);
}
var_export(array_merge($result, ...$pool));
Alternatively without array_merge() and count() calls, but it makes more iterated calls of array_shift(): (Demo)
$pool = [$first, $second, $third, $fourth];
$result = [];
while ($pool) {
$pullFrom = array_rand($pool);
if (!$pool[$pullFrom]) {
unset($pool[$pullFrom]);
continue;
}
$result[] = array_shift($pool[$pullFrom]);
}
var_export($result);
Loop this script until both arrays are done.
$j = 0;
$i = 0;
$r = rand(0, 1);
if($r == 0) {
$ret .= $array1[$i];
$i++;
} elseif($r == 1) {
$ret .= $array2[$j];
$j++;
}
Of course, you have to handle a few exceptions in this code, but it might be the route.
Suppose i have a number let's say 5. Now lets assume that there are 5 members. Now each member started to count 1 to 2. Those member who get 2nd number leaves and then again count start from the next member. so at last in this scenario the 3rd member stays at last.
So i tried to implement like this. First of assign members as array $v.
for($i=1 ; $i<=5 ; $i++)
{
$v[] = $i;
}
$v1 = array_flip($v);
for($i=0 ; $i<=5 ; $i += 2 )
{
unset($v1[$i]);
}
echo "<pre>";
print_r($v1);
output
Array
(
[1] => 0
[3] => 2
[5] => 4
)
Now i want to count the numbers from key 5(5th member) to again 1(1st member) and so on.
so at last key 3(3rd member) left.
I want to print the last member that left.
How can i achieve this?
I you can't understand then look at this
Survival Strategy
Here's an Object-Oriented solution with an easy-to-follow reduce method and multiple examples.
class CountByTwoArrayReducer {
public function __construct($array) {
$this->array = $array;
$this->size = count($array);
}
public function reduce() {
$this->initialize();
while($this->hasMultipleItems()) {
$this->next();
$this->removeCurrentItem();
$this->next();
}
return $this->finalItem();
}
protected function initialize() {
$this->current = 1;
$this->removed = array();
$this->remaining = $this->size;
}
protected function hasMultipleItems() {
return ($this->remaining > 1);
}
protected function next($start = null) {
$next = ($start === null) ? $this->current : $start;
do {
$next++;
} while(isset($this->removed[$next]));
if($next > $this->size)
$this->next(0);
else
$this->current = $next;
}
protected function removeCurrentItem() {
$this->removed[$this->current] = 1;
$this->remaining--;
}
protected function finalItem() {
return $this->array[$this->current - 1];
}
}
$examples = array(
array('A', 'B', 'C', 'D', 'E'),
range(1, 100),
range(1, 1000),
range(1, 10000)
);
foreach($examples as $example) {
$start = microtime(true);
$reducer = new CountByTwoArrayReducer($example);
$result = $reducer->reduce();
$time = microtime(true) - $start;
echo "Found {$result} in {$time} seconds.\n";
}
This will remove every other item from the array until there is only a single item left.
$members = range(1, 5);
$i = 0;
while(count($members) > 1) {
$i++;
if($i == count($members)) $i = 0;
unset($members[$i]);
$members = array_values($members);
if($i == count($members)) $i = 0;
}
echo $members[0];
Hmm, I can recommend two functions:
http://php.net/manual/en/function.array-keys.php
This would re-index you array, with indexes: 0, 1, 2
http://php.net/manual/en/control-structures.foreach.php
With this you can go through any array by:
foreach($v1 as $key=>$value) { ...select maximum, etc. ... }
<?php
function build_thieves($thieves)
{
return range(1, $thieves);
}
function kill_thief(&$cave)
{
if(sizeof($cave)==1)
{
$thief=array_slice($cave, 0, 1);
echo $thief.' survived';
return false;
}
$thief=array_slice($cave, 0, 1);
array_push($cave, $thief);
$thief=array_slice($cave, 0, 1);
echo $thief.' killed';
return true;
}
$cave=build_thieves(5);
$got_data=true;
while($got_data)
{
$got_data=kill_thief($cave);
}
Adjusted to every 2nd, not every 3rd. And starting from 1 not 0
This answer is a bit more complex, but it is much more efficient. It doesn't create an array of items and then remove them. It starts with a value (e.g. 1) and calculates the next item that has not been removed yet. Then, it flags it as removed. If you actually have an array of items, the index of the final item will be $current - 1. The example below uses values 1 through 10,000. On my machine, it takes just over 0.05 seconds.
define('SIZE', 10000);
/**
* Helper function to return the next value
*/
function get_next($current, &$removed) {
$next = $current;
do {
$next++;
} while(isset($removed[$next]));
return ($next > SIZE) ? get_next(0, $removed) : $next;
}
$current = 1;
$removed = array();
$remaining = SIZE;
$start_time = microtime(true);
while($remaining > 1) {
$current = get_next($current, $removed);
$removed[$current] = 1;
$remaining = SIZE - count($removed);
$current = get_next($current, $removed);
}
$total_time = microtime(true) - $start_time;
echo "Processed " . SIZE . " items\n";
echo "Winning item: {$current}\n";
echo "Total time: {$total_time} seconds\n";
This question already has answers here:
PHP get the item in an array that has the most duplicates
(2 answers)
Closed 1 year ago.
I have an array of numbers like this:
$array = array(1,1,1,4,3,1);
How do I get the count of most repeated value?
This should work:
$count=array_count_values($array);//Counts the values in the array, returns associatve array
arsort($count);//Sort it from highest to lowest
$keys=array_keys($count);//Split the array so we can find the most occuring key
echo "The most occuring value is $keys[0][1] with $keys[0][0] occurences."
I think array_count_values function can be useful to you. Look at this manual for details : http://php.net/manual/en/function.array-count-values.php
You can count the number of occurrences of values in an array with array_count_values:
$counts = array_count_values($array);
Then just do a reverse sort on the counts:
arsort($counts);
Then check the top value to get your mode.
$mode = key($counts);
If your array contains strings or integers only you can use array_count_values and arsort:
$array = array(1, 1, 1, 4, 3, 1);
$counts = array_count_values($array);
arsort($counts);
That would leave the most used element as the first one of $counts. You can get the count amount and value afterwards.
It is important to note that if there are several elements with the same amount of occurrences in the original array I can't say for sure which one you will get. Everything depends on the implementations of array_count_values and arsort. You will need to thoroughly test this to prevent bugs afterwards if you need any particular one, don't make any assumptions.
If you need any particular one, you'd may be better off not using arsort and write the reduction loop yourself.
$array = array(1, 1, 1, 4, 3, 1);
/* Our return values, with some useless defaults */
$max = 0;
$max_item = $array[0];
$counts = array_count_values($array);
foreach ($counts as $value => $amount) {
if ($amount > $max) {
$max = $amount;
$max_item = $value;
}
}
After the foreach loop, $max_item contains the last item that appears the most in the original array as long as array_count_values returns the elements in the order they are found (which appears to be the case based on the example of the documentation). You can get the first item to appear the most in your original array by using a non-strict comparison ($amount >= $max instead of $amount > $max).
You could even get all elements tied for the maximum amount of occurrences this way:
$array = array(1, 1, 1, 4, 3, 1);
/* Our return values */
$max = 0;
$max_items = array();
$counts = array_count_values($array);
foreach ($counts as $value => $amount) {
if ($amount > $max) {
$max = $amount;
$max_items = array($value);
} elif ($amount = $max) {
$max_items[] = $value;
}
}
$vals = array_count_values($arr);
asort($vals);
//you may need this end($vals);
echo key($vals);
I cant remember if asort sorts asc or desc by default, you can see the comment in the code.
<?php
$arrrand = '$arr = array(';
for ($i = 0; $i < 100000; $i++)
{
$arrrand .= rand(0, 1000) . ',';
}
$arrrand = substr($arrrand, 0, -1);
$arrrand .= ');';
eval($arrrand);
$start1 = microtime();
$count = array_count_values($arr);
$end1 = microtime();
echo $end1 - $start1;
echo '<br>';
$start2 = microtime();
$tmparr = array();
foreach ($arr as $key => $value);
{
if (isset($tmparr[$value]))
{
$tmparr[$value]++;
} else
{
$tmparr[$value] = 1;
}
}
$end2 = microtime();
echo $end2 - $start2;
Here check both solutions:
1 by array_count_values()
and one by hand.
<?php
$input = array(1,2,2,2,8,9);
$output = array();
$maxElement = 0;
for($i=0;$i<count($input);$i++) {
$count = 0;
for ($j = 0; $j < count($input); $j++) {
if ($input[$i] == $input[$j]) {
$count++;
}
}
if($count>$maxElement){
$maxElement = $count;
$a = $input[$i];
}
}
echo $a.' -> '.$maxElement;
The output will be 2 -> 3
$arrays = array(1, 2, 2, 2, 3, 1); // sample array
$count=array_count_values($arrays); // getting repeated value with count
asort($count); // sorting array
$key=key($count);
echo $arrays[$key]; // get most repeated value from array
String S;
Scanner in = new Scanner(System.in);
System.out.println("Enter the String: ");
S = in.nextLine();
int count =1;
int max = 1;
char maxChar=S.charAt(0);
for(int i=1; i <S.length(); i++)
{
count = S.charAt(i) == S.charAt(i - 1) ? (count + 1):1;
if(count > max)
{
max = count;
maxChar = S.charAt(i);
}
}
System.out.println("Longest run: "+max+", for the character "+maxChar);
here is the solution
class TestClass {
public $keyVal;
public $keyPlace = 0;
//put your code here
public function maxused_num($array) {
$temp = array();
$tempval = array();
$r = 0;
for ($i = 0; $i <= count($array) - 1; $i++) {
$r = 0;
for ($j = 0; $j <= count($array) - 1; $j++) {
if ($array[$i] == $array[$j]) {
$r = $r + 1;
}
}
$tempval[$i] = $r;
$temp[$i] = $array[$i];
}
//fetch max value
$max = 0;
for ($i = 0; $i <= count($tempval) - 1; $i++) {
if ($tempval[$i] > $max) {
$max = $tempval[$i];
}
}
//get value
for ($i = 0; $i <= count($tempval) - 1; $i++) {
if ($tempval[$i] == $max) {
$this->keyVal = $tempval[$i];
$this->keyPlace = $i;
break;
}
}
// 1.place holder on array $this->keyPlace;
// 2.number of reapeats $this->keyVal;
return $array[$this->keyPlace];
}
}
$catch = new TestClass();
$array = array(1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 3, 1, 2, 3, 1, 1, 2, 5, 7, 1, 9, 0, 11, 22, 1, 1, 22, 22, 35, 66, 1, 1, 1);
echo $catch->maxused_num($array);