I have got a series like this:
14, 13, 12, 14, 15, 18, 20, 17, 15, 19, 22, 24, 22, 18, 15, 14, 17, ...
If I plot these points on a chart on X-Y axis using these values as Y coordinates, then you'll see that there are peaks at 20 & 24.
I want to find all these peaks in the series
I tried:
$a=array(14, 13, 12, 14, 15, 18, 20, 17, 15, 19, 22, 24, 22, 18, 15, 14, 17 );
rsort($a);
echo $a[0];
echo $a[1];
But that doesn't give me the two peaks I see on the graph. The result of the code above is 24, and 22. But the peak on the graph were made by 20 and 24...
Is there a way I can detect the array to determine the peaks in the entire series?
I don't need a working code. Just some ideas I can work upon.
As Mark Baker suggested, you need to check that each value in the array is greater than the previous and the next value. That's what defines a peak.
Just be sure to start from the 2nd index and finish on the nth-1 item or else you'll get an Undefined offset error.
$a = array(14, 13, 12, 14, 15, 18, 20, 17, 15, 19, 22, 24, 22, 18, 15, 14, 17);
$arr = [];
for($i=1; $i<count($a)-1; $i++){
if($a[$i] > $a[$i+1] && $a[$i] > $a[$i-1]) {
array_push($arr, $a[$i]);
}
}
var_dump($arr); //returns: array(2) { [0]=> int(20) [1]=> int(24) }
Depending on your application, you might want to add some logic in case the case that 2 or more items "together" are a peak. For example, 22, 24, 24, 22, 18. If this is something you want, just change the logic to check for >= on the next item:
if($a[$i] > $a[$i+1] && $a[$i] >= $a[$i-1]) {
This will yield the same result as above.
<?php
$a=array(14, 13, 12, 14, 15, 18, 20, 17, 15, 19, 22, 24, 22, 18, 15, 14, 17 );
$last=0;
$peaks=array();
$upwards=false;
foreach( $a as $value )
{
if( $value > $last )
{
$upwards = true;
}
if( $value < $last )
{
if( $upwards )
{
$peaks[] = $last;
}
$upwards = false;
}
$last = $value;
}
var_dump($peaks);
Old question, guess it popped up because someone was editing, but here's my two cents' worth. This is better done without a loop:
<?php
$a = [14, 13, 12, 14, 15, 18, 20, 17, 15, 19, 22, 24, 22, 18, 15, 14, 17];
$b = array_filter(
$a,
function($v, $k) use($a) {return $k > 0 && $v > $a[$k-1] && $k + 1 < count($a) && $v > $a[$k+1];},
ARRAY_FILTER_USE_BOTH
);
print_r($b);
Result:
Array
(
[6] => 20
[11] => 24
)
Related
I'm looking for a solution to run the PHP loop into tens. This question is hard to phrase but I will try to keep it simple.
First, this is my code.
function custom_betcurry_s_in_s( $hey_stack, $needle ){
return strpos( $hey_stack , $needle ) !== false;
}
$data = '1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,22,23';
$array = explode( ',', $data );
$total = count( $array );
// how many tens do we have here
// the first one is from 0 to 9
// how many tens
$my_tens = $total / 10;
$loops_parts = explode( '.', $my_tens );
$loops = $loops_parts[0];
$remainder = $loops_parts[1];
for( $i = 1; $i < ( (int) $loops + 1 ); $i++ ){
//echo $i;
//$start = $i
// here section my $array into 10s
// like this
// I'm stuck here
}
// Desired out put should be
// first string = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
// second string = 11, 12, 13, 14, 15, 16, 17, 18, 19, 20
// 3rd string 21, 22, 23
the idea is to run loops in 10s, if I have 40 items in my array then the loop should be executed 4 times with 4 strings if 60 then the loop to be executed 6 times with 6 strings, if 64, the loop to be executed 7 times, that is 6 times from 0 to 60 and 7th time from 61 to 64 and so on and so forth
Given a two list. Create a third list by picking an odd-index element from the first list and even index elements from the second.
For Example:
listOne = [3, 6, 9, 12, 15, 18, 21]
listTwo = [4, 8, 12, 16, 20, 24, 28]
Expected Output:
Printing Final third list
[6, 12, 18, 4, 12, 20, 28]
I think, it will be helpful for you.
<?php
$listOne = [3, 6, 9, 12, 15, 18, 21];
$listTwo = [4, 8, 12, 16, 20, 24, 28];
$NlistOne=[];
$NlistTwo=[];
//odd-index positions from list one [6, 12, 18]
foreach ($listOne as $key => $value) {
if($key%2==1){
array_push($NlistOne, $value);
}
}
//even-index positions from list two [4, 12, 20, 28]
foreach ($listTwo as $key => $value) {
if($key%2==0){
array_push($NlistTwo, $value);
}
}
//Printing Final third list [6, 12, 18, 4, 12, 20, 28]
print_r(array_merge($NlistOne,$NlistTwo));
?>
Output will be:
Array ( [0] => 6 [1] => 12 [2] => 18 [3] => 4 [4] => 12 [5] => 20 [6] => 28 )
//init result array
//loop over listOne, using for($i=1;$i<sizeof($listOne);$i=$i+2)
//and add to result for each iteration, $resultArr[] = $listOne[$i]
//do the same with listTwo, but for($i=*0*
You can merge both of arrays and then pick all odd elements
$listOne = [3, 6, 9, 12, 15, 18, 21];
$listTwo = [4, 8, 12, 16, 20, 24, 28];
$result = [];
foreach ( array_merge($listOne, $listTwo) as $value ){
if ( $key % 2 ) {
$result[] = $value;
}
}
If array length isn't fixed, say it could contain not 7 elements, then you need to check it before merging to make it have odd number of elements
$listOne = [3, 6, 9, 12, 15, 18, 21, 777];
$listTwo = [4, 8, 12, 16, 20, 24, 28];
$result = [];
if ( count($listOne) % 2 !== 1 ) {
$listOne[] = 0;
}
foreach( array_merge($listOne, $listTwo) as $value ){
if ( $key % 2 ) {
$result[] = $value;
}
}
you don't have to loop over whole array array_filter will do this for you, Constant ARRAY_FILTER_USE_KEY will check each key for odd or for even
<?php
$a1 = [3, 6, 9, 12, 15, 18, 21];
$a2 = [4, 8, 12, 16, 20, 24, 28];
function odd($var)
{
// returns whether the input integer is odd
return $var & 1;
}
function even($var)
{
// returns whether the input integer is even
return !($var & 1);
}
$result= (array_merge(array_filter($a1, 'odd', ARRAY_FILTER_USE_KEY),array_filter($a2, 'even', ARRAY_FILTER_USE_KEY)));
output you will get
Array (
[0] => 6
[1] => 12
[2] => 18
[3] => 4
[4] => 12
[5] => 20
[6] => 28 )
Iterate over first one and take only values of odds indices, and loop again through second one and take evens indices.
$listOne = [3, 6, 9, 12, 15, 18, 21];
$listTwo = [4, 8, 12, 16, 20, 24, 28];
$res = [];
for ($i=0; $i < count($listOne); $i++) {
if($i & 1) // $i is odd.
$res[] = $listOne[$i];
}
for ($j=0; $j < count($listTwo); $j++) {
if(n % 2 === 0) // $j is even.
$res[] = $listTwo[$j];
}
Result:
echo "List One :".json_encode($listOne)."<br>";
echo "List Two :".json_encode($listTwo)."<br>";
echo "Lists Merged:".json_encode($res);
Output:*
/*
List One :[3,6,9,12,15,18,21]
List Two :[4,8,12,16,20,24,28]
Lists Merged:[6,12,18,4,12,20,28]
*/
Iterate over arrays:
take odds in array starting with index One and increment it by two.
take evens in array by starting with index Zero and increment it by two.
$listOne = [3, 6, 9, 12, 15, 18, 21]; $listTwo = [4, 8, 12, 16, 20, 24, 28];
$res = [];
for ($i=1; $i < count($listOne); $i+=2) {
$res[] = $listOne[$i];
}
for ($j=0; $j < count($listTwo); $j+=2) {
$res[] = $listTwo[$j];
}
print(json_encode($res)); // [6,12,18,4,12,20,28]
First time posting on stackoverflow.
After printing the main array, I have managed to highlight the values that are found in the second one, but I also want to print the number of times that the duplicate occurs in brackets at the same time. I have run out of the ideas on how to do that last part, I get stuck in multiple loops and other problems. I will paste here what's working for now.
The code:
$main = array( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20 );
$secondary = array( 1, 6, 10, 6, 17, 6, 17, 20 );
foreach ( $main as $number )
{
if ( in_array( $number, $secondary ) )
{
echo $item;
// this one is supposed to be highlighted, but the html code disappears on stackoverflow
/* this is where the number of duplicates should appear in bracket, example:
highlighted number( number of duplicates ) */
}
else
{
echo $item;
// this one is simple
}
}
EXPECTED RESULT:
1(1), 2, 3, 4, 5, 6(3), 7, 8, 9, 10(1), 11, 12, 13, 14, 15, 16, 17(2), 18, 19, 20(1)
Basically the brackets contain the number of times that the value is found in the second array, aside from being colored, but I can't paste the html code for some reason. Sorry for not making the expected result more clear !
PROBLEM SOLVED:
Thanks to everyone for your help, first time using this website, didn't expect such a quick response from you guys. Thank you very much !
You need to get the count values of your secondary array first using array_count_values. This is what you can acquire as
$main = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20);
$secondary = array(1, 6, 10, 6, 17, 6, 17, 20);
$count_values = array_count_values($secondary);
foreach ($main as $key => $value) {
if (in_array($value, $secondary)) {
echo $value . "<strong>(" . $count_values[$value] . ")</strong>";
echo ( ++$key == count($main)) ? '' : ',';
} else {
echo $value;
echo ( ++$key == count($main)) ? '' : ',';
}
}
Output:
1(1),2,3,4,5,6(3),7,8,9,10(1),11,12,13,14,15,16,17(2),18,19,20(1)
Assuming $secondary is the one with the dupes, you should go about it the other way:
$dupes = array();
foreach($secondary as $number) {
if (in_array($number, $main)) {
$dupes[$number]++;
}
}
var_dump($dupes);
<?php
$main = array( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,12, 13, 14, 15, 16, 17,18,19,20);
$secondary = array( 1, 6, 10, 6, 17, 6, 17, 20 );
$result =array();
foreach($main as $key => $value){
$i=0;
foreach($secondary as $key1 => $value1){
if($value == $value1){
$i++;
}
$result[$value] = $i;
}
}
$resultString ='';
foreach($result as $key => $value){
$resultString .=$key.'('.$value.'),' ;
}
echo trim($resultString,',');
?>
Result:
1(1),2(0),3(0),4(0),5(0),6(3),7(0),8(0),9(0),10(1),11(0),12(0),13(0),14(0),15(0),16(0),17(2),18(0),19(0),20(1)
I have an array in PHP which has associative index values as show below. They are irrelevant to the sorting that I need to do, but I need to keep them.
Each value in this array is actually another array which might have 1 to N integers in it, sorted in descending order. However, the integers are written down as text (strings). So the initial data looks something like that:
[10025] => 51, 51, 43, 43, 30, 29, 28, 27, 25, 24, 22, 21
[15671] => 24, 21
[02672] => 24, 26
[76935] => 87, 72, 69, 67, 55, 43, 43, 40, 35, 33, 29
I need to sort this by looking at the maximum value of each secondary array. If the values are equal, I have to look at the second value, etc so finally I'll get something like this:
[76935] => 87, 72, 69, 67, 55, 43, 43, 40, 35, 33, 29
[10025] => 51, 51, 43, 43, 30, 29, 28, 27, 25, 24, 22, 21
[02672] => 24, 26
[15671] => 24, 21
arsort() by default looks at the number of items in each array, which doesn't do the job and raising the SORT_NUMERIC doesn't work either - can't figure out what it does exactly but it doesn't sort the array the way I want.
I've also looked at array_multisort(), however, playing around with it, I couldn't get the desired result either.
Try this, take note of the uasort() function (that's where the magic happens):
<?php
$data = array(
10025 => '51, 51, 43, 43, 30, 29, 28, 27, 25, 24',
15671 => '24, 21',
02672 => '24, 26',
76935 => '87, 72, 69, 67, 55, 43, 43, 40, 35, 33, 29'
); //Inital data array
echo '<pre>'.print_r($data, true).'</pre>'; //Print the array as it is
uasort($data, function($a, $b) { //Sort the array using a user defined function maintaining array indices
$aArray = explode(', ', $a); //Split the strings into proper arrays
$bArray = explode(', ', $b);
rsort($aArray); //Sort the proper arrays from largest to smallest
rsort($bArray);
return $aArray[0] > $bArray[0] ? -1 : 1; //Compare the first element in each array (because it is the largest thanks to the rsort functions)
});
echo '<pre>'.print_r($data, true).'</pre>'; //Print the array in it's new order
?>
Output:
Array
(
[10025] => 51, 51, 43, 43, 30, 29, 28, 27, 25, 24
[15671] => 24, 21
[1466] => 24, 26
[76935] => 87, 72, 69, 67, 55, 43, 43, 40, 35, 33, 29
)
Array
(
[76935] => 87, 72, 69, 67, 55, 43, 43, 40, 35, 33, 29
[10025] => 51, 51, 43, 43, 30, 29, 28, 27, 25, 24
[1466] => 24, 26
[15671] => 24, 21
)
array_multisort() should do the trick:
$yourdata; // your assosiative array with data
$lengths = array();
foreach ($yourdata as $key => $row)
{
$lengths[$key] = $row.length;
}
array_multisort($lengths, SORT_DESC, $yourdata);
Reference url http://www.php.net/manual/ro/function.array-multisort.php
uasort(
$myArray,
function($a, $b) {
$a = explode(',',$a);
$b = explode(',',$a);
$i = 0;
while (true) {
if (isset($a[$i]) && isset($b[$i]) && $a[$i] !== $b[0]) {
return ($a[$i] < $b[$i]) ? -1 : 1;
} elseif (isset($a[$i]) && !isset($b[$i])) {
return 1;
} elseif (isset($b[$i]) && !isset($a[$i])) {
return -1;
} elseif (!isset($b[$i]) && !isset($a[$i])) {
return 0;
}
$i++;
}
}
);
Is there a neat way to split an array into chunks based on an array of lengths?
Input:
$start = range(0, 30);
$length = [3, 7, 2, 12, 6];
Desired Output:
[
[0, 1, 2], // 3
[4, 5, 6, 7, 8, 9, 10], // 7
[11, 12], // 2
[13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24], // 12
[25, 26, 27, 28, 29, 30], // 6
];
Using array_splice:
$target = array(); // or use [] in PHP 5.4
foreach($length as $i) {
$target[] = array_splice($start, 0, $i);
}
Try it.
Be advised, this changes $start!
This is very easily accomplished with the following:
Code:
$target = array();
$offset = 0;
foreach ($length as $lengthValue) {
$target[] = array_slice($start, $offset, $lengthValue);
$offset += $lengthValue;
}
var_dump($target);
Explanation:
What you are doing here is using the array_slice() method (very similar to the substr) to extract the portion of the array and then inserting it into the target array. Incrementing the offset each time allows the function to remember which one to use next time.