I have array value like this :
$src = array(3,15,16,17,18,20,25,7);
How can i split it into :
array(
[0] => 3,
[1] => array([0] => 15, [1] => 18),//when value is range get start and end
[2] => 20,
[3] => 25,
[4] =>
);
Check this code. If your sequence/range difference is based on only next numbers, then this code would work for you.
<?php
$src = array(3,15,16,17,18,20,25,7);
$tot = count($src);
$resarr = array();
$st = $ed = '';
for($i=0;$i<$tot;$i++){
if($st==''){
if(isset($src[$i+1]) && $src[$i+1] == $src[$i]+1){
$st = $src[$i];
}
}
else{
if(!isset($src[$i+1]) || $src[$i+1] != $src[$i]+1){
$ed=$src[$i];
}
}
if($st=='' && $ed==''){
$resarr[] = $src[$i];
}
elseif($st!='' && $ed!=''){
$resarr[] = array($st,$ed);
$st = $ed='';
}
}
print_r($src);
echo "<pre>";print_r($resarr);echo "</pre>";
?>
Also phpfiddle example is here http://phpfiddle.org/lite/code/k7c4-wvdg. Keep practice write your own logic.
// Make copy of array with shifting to one item.
// And, to save array length, add one element to the end of the array.
// It can be any number, but not continue sequence.
// I add the last item of source array
$src1 = $src;
array_shift($src1);
array_push($src1,end($src));
// Then subtract corresponding items of array
$temp = array_map(function ($i, $j) { return $j-$i; }, $src, $src1);
// Look at arrays
// $src 3, 15, 16, 17, 18, 20, 25, 7
// $temp 12, 1, 1, 1, 2, 5, -18, 0,
// As you can see, all elements of sequences, but the last, has 1 in `temp` array.
// Therefore, we just need to collect the result
$sarr = false;
$result = array();
for($i=0; $i<count($src); $i++) {
if($temp[$i] == 1) {
if(! $sarr) {
$sarr = $src[$i];
}
}
else {
if(! $sarr) {
$result[] = $src[$i];
}
else {
$result[] = [$sarr, $src[$i]];
$sarr = false;
}
}
}
print_r($result);
Test it there
I added some values just to cover edge cases. Comments explain.
<?php
$src = array(3,4,15,16,17,18,20,25,7,8);
$res = [];
$start = null;
//Rather than make a counter use a for loop
for($i=0; $i < count($src); $i++){
//Make sure i+1 is not bigger than array
//If current index value + 1
//Euqals the next index value we have a range
if($i+1 < count($src) && $src[$i]+1 == $src[$i+1]){
if($start === null){
$start = $i;
}
//Once the range is over we can use the current index as end
} elseif($start !== null){
$res[] = array($src[$start], $src[$i]);
$start = null;
$end = null;
//There was never a range.
} else {
$res[] = $src[$i];
}
}
echo "<pre>";
print_r($res);
Results:
Array
(
[0] => Array
(
[0] => 3
[1] => 4
)
[1] => Array
(
[0] => 15
[1] => 18
)
[2] => 20
[3] => 25
[4] => Array
(
[0] => 7
[1] => 8
)
)
Related
foreach($manualsArray as $manuls){
for($i=0;$i<=count($manuls);$i++){
if($i/2 == 0){
$manuls = 23;
print($manuls);
}
else{
$manualsArray= 98;
print($manualsArray);
}
print($manualsArray);
}
}
I want to create key value pairs according to index like 0 is key 1 is value 2 is key 3 is value and so on.
the sample input is write below
Array
(
[0] => Array
(
[0] => Faucet Centers
[1] => 6, 4, 13, 12, 7, 10, 14, 16, 8, 5, 9, 15, 11 in.
[2] => Flow Rate (GPM)
[3] => 1.2
[4] => Height
[5] => 5.875 in.
[6] => Max Deck Thickness
[7] => 2.25 in.
[8] => Spout Height
[9] => 3.625 in.
[10] => Spout Reach
[11] => 5 in.
)
)
You can achieve this by changing your loop to increment by 2 each time and take $i as the key and $i+1 as the value...
$output = [];
foreach($manualsArray as $manual){
$m = [];
for ( $i = 0; $i < count($manual); $i+=2 ) {
$m [$manual[$i]] = $manual[$i+1];
}
$output [] = $m;
}
print_r($output);
you can use array_chunk()
foreach($manualsArray as $manuls){
foreach( array_chunk($manuls, 2) as $pair) {
echo 'key: ' . $pair[0] . ' is value: '. $pair[1] . "<br>/n";
}
}
or if you want an associative array
$result_array = [];
foreach($manualsArray as $manuls){
foreach( array_chunk($manuls, 2) as $pair) {
$result_array[] = [$pair[0] => $pair[1]];
}
}
var_export($result_array);
https://www.php.net/manual/en/function.array-chunk.php
Use modulo for that:
<?php
$newarray = array();
foreach($yourarray[0] as $id => $val){
if($id % 2 == 0){
$last_index = $val;
}else{
$newarray[$last_index] = $val;
}
}
?>
I assume that your array is the one you have given, so it's 2-dimensional.
If not, use $yourarray instead of $yourarray[0].
Im trying to parse an array in PHP to fill Null values as averages between the closest two values before inserting into MySQL (5). I have currently tried the below code but the code moves the pointer for the entire array when I call next($value['wind']).
f_data:
(
[2019-05-06 09:00:00] => Array
(
[temp] => 50
[wind] => 10
[rain] => 50
)
[2019-05-06 10:00:00] => Array
(
[temp] => 65
)
[2019-05-06 11:00:00] => Array
(
[temp] => 70
[wind] => 8
[rain] => 30
)
)
code thus far:
foreach ($f_data as $key => $value) {
$f_weather_date = $key;
$future_weather = $value['temp'];
if ($value['wind'] > 0) {
$f_wind = $value['wind'];
$f_wind_last = $f_wind;
} else {
$f_wind = $f_wind_last;
$x = 0;
$f_wind_next = 0;
for ($x = 0; $f_wind_next = 0; $x++) {
$f_wind_next = next($value['wind']);
return $x;
}
$f_wind = ($f_wind_next + $f_wind_last) / $x;
}
if ($value['rain'] > 0) {
$f_rain = $value['rain'];
$f_rain_last = $f_rain;
} else {
$f_rain = $f_rain_last;
}
$sql = "INSERT INTO `Table` (`Date`, `Temp`, `Wind`, `Rain`) VALUES ('$f_weather_date', $future_weather, $f_wind, $f_rain)";
mysqli_query($conn, $sql);
}
Expected results would return [wind] => 9 and [rain] => 40 at 10:00:000
First extract the keys and then iterate with int key. This way you can calculate the average easily.
Consider:
$keys = array_keys($f_data);
$arr = array_values($f_data);
foreach($arr as $k => &$v) {
if (!isset($v['rain']) { //you can do the same for wind
$v = ($arr[$k -1]['rain'] + $arr[$k +1]['rain']) /2;
}
}
Now return the original keys with:
$f_data = array_combine($keys, $arr);
Notice you need to take care of case the last eleme t is missing data and when 2 neighbors elements missing data
What is the best way to split the following array to different combinations according to number of values?
[0] => 1
[1] => 5
[2] => 4
[3] => 1
[4] => Array
(
[0] => 1
[1] => 9
)
To
[0] => 1
[1] => 5
[2] => 4
[3] => 1
[4] => 1
AND
[0] => 1
[1] => 5
[2] => 4
[3] => 1
[4] => 9
function getCombinations($arr){
$ret = array();
$subs = array();
// extract sub arrays
$n = count($arr);
for($i=0;$i<$n;$i++){
if(is_array($arr[$i])){
$subs[] = array('target'=>$i, 'values'=>$arr[$i], 'size'=>count($arr[$i]), 'counter'=>0);
$arr[$i] = null;
}
}
$subs_n = count($subs);
if($subs_n==0) // no subarrays found, return input
return $arr;
$finished = false;
while(!$finished){
$combination = $arr; // this will copy the existing array
for($i=0;$i<$subs_n;$i++){
$combination[$subs[$i]['target']] = $subs[$i]['values'][$subs[$i]['counter']]; // write current combination into designated index
}
$ret[] = $combination; // add combination to output
$carry = true;
$i = 0;
while($carry){
$subs[$i]['counter']++; //next combination
if($subs[$i]['counter']>=$subs[$i]['size']){ // if end of combination, increment next level
$carry = true;
$subs[$i]['counter'] = 0;
}else{
$carry = false;
}
$i++;
if($i>=$subs_n && $carry){ // if last combination reached, all done
$finished = true;
$carry = false;
}
}
}
return $ret;
}
I'd go with something like this:
<?php
$arr = [
0 => 1,
1 => 5,
2 => 4,
3 => 1,
4 => [
0 => 1,
1 => 9,
]
];
$arr = [
0 => null,
1 => $arr,
];
function split_array($a) {
$ended = true;
$new_line = [];
$rem_line = [];
$last_line = array_pop($a);
foreach ($last_line as $k=>$v){
if ( is_array( $v ) ) {
$new_v = array_shift($v);
if ( count($v) > 0 ) {
$rem_v = $v;
$ended = false;
} else {
$rem_v = $new_v;
}
} else {
$new_v = $v;
$rem_v = $v;
}
$new_line[] = $new_v;
$rem_line[] = $rem_v;
}
$a[] = $new_line;
if ( ! $ended ) {
echo 'not ended';
$a[] = $rem_line;
$a = split_array($a);
}
return $a;
}
array_shift($arr);
echo '<pre>';
print_r( split_array($arr) );
echo '</pre>';
I try to write a script and a problem. Can you let me know if you know how i can do this or ask someone if they know how can this be possibe.
Max numbers which can be selected 1 to 20 numbers. it can loop and select any number between 1-20
ignore these numbers e.g. 1,2,4,6,9,12 this will be array which can change.
each array line can have upto 4 numbers
Each array line needs to be unique
5.I need to have around 10 arrays unique
Max 2 numbers can match previous numbers see below.
How can i go about doing this. Any help would be great.
e.g.
Array(
[0] => Array
(
[0] => 3
[1] => 16
[2] => 22
[3] => 24
)
[1] => Array
(
[0] => 3
[1] => 16
[2] => 7
[3] => 13
)
[2] => Array
(
[0] => 20
[1] => 17
[2] => 10
[3] => 18
)
)
This not allow as some array match each other
Array(
[0] => Array
(
[0] => 3
[1] => 16
[2] => 22
[3] => 24
)
[1] => Array - cant have this as 3 of the numbers matchs the previous array.only two numbers can match.
(
[0] => 3
[1] => 16
[2] => 22
[3] => 13
)
[2] => Array
(
[0] => 20
[1] => 17
[2] => 10
[3] => 18
)
)
Thank you.
This seems to satisfy your conditions: http://codepad.viper-7.com/WHkQeD
<?php
$num_arrays = 10; $num_elements = 4;
$min = 1; $max = 20;
$exclude_numbers = array( 1, 4, 6); // Add numbers here to exclude
$answer = array();
for( $i = 0; $i < $num_arrays; $i++)
{
$answer[$i] = array();
for( $j = 0; $j < $num_elements; $j++)
{
do
{
$current = rand( $min, $max);
// If the previous array exists and there are more than two common elements when we add the $current element, continue
if( isset( $answer[$i-1]) && count( array_intersect( $answer[$i-1], array_merge( $answer[$i], array( $current))) > 2)
{
continue;
}
} while( in_array( $current, $exclude_numbers) || in_array( $current, $answer[$i]));
$answer[$i][$j] = $current;
}
}
var_dump( $answer);
Edit: Here is a complete solution that satisfies all of your criteria.
Demo
<?php
$num_arrays = 10; $num_elements = 4;
$min = 1; $max = 20;
$exclude_numbers = array( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13);
$answer = array();
for( $i = 0; $i < $num_arrays; $i++)
{
$answer[$i] = array();
for( $j = 0; $j < $num_elements; $j++)
{
do
{
// Get a random element
$current = rand( $min, $max);
$new_array = array_merge( $answer[$i], array( $current));
// If the previous array has more than two common elements (because of the added $current), get a new $current
if( isset( $answer[$i-1]) && count( array_intersect( $answer[$i-1], $new_array)) > 2)
{
$answer[$i] = array_diff( $new_array, $answer[$i-1]);
$j = count( $answer[$i]) - 1;
continue;
}
} while( in_array( $current, $exclude_numbers) || in_array( $current, $answer[$i]));
$answer[$i][$j] = $current;
// If the array is complete, we need to check for unique arrays
if( count( $answer[$i]) == $num_elements)
{
$k = $i - 1;
while( $k >= 0)
{
if( count( array_diff( $answer[$k], $answer[$i])) == 0)
{
// This array is the same as a previous one, start over
$answer[$i] = array();
$j = -1;
break;
}
$k--;
}
// Optionally sort each array
sort( $answer[$i]);
}
}
}
var_dump( $answer);
somthing like:
function generate_list($max, $forbidden)
{
$list = array();
while(count($list) < 4)
{
$new = rand(1, $max);
if(in_array($new, $forbidden))
{
continue;
}
$list[] = $new;
$forbidden[] = $new;
}
return $list;
}
function count_max_same($new_list, $old_lists)
{
$max_same = 0;
foreach($old_lists as $current_list)
{
$max_same = max($max_same, count(array_intersect($new_list, $old_lists)));
}
return $max_same;
}
function generate_unique_lists($count_of_lists, $max, $forbidden, $max_same = 2, $max_tries = 1000)
{
$lists = array();
while($max_tries-- AND count($lists) < $count_of_lists)
{
$new_list = generate_list($max, $forbidden);
if(count_max_same($new_list, $lists) <= $max_same)
{
$lists[] = $new_list;
}
}
return $lists;
}
iam trying to build a multidimensional array.
public function saveRateTemplateData($RateTemplateInfo)
{
$RateTemplateID = $RateTemplateInfo['id'];
$Zones = $RateTemplateInfo['premium_zones'];
//$ZoneZipCodeIDs[] = array();
for ($n = 1; $n <= $RateTemplateInfo['premium_zones']; $n++) {
$ZoneNum = 'zone' . $n;
$ZipCodeArray = explode(",",$_POST[$ZoneNum]);
$ZipCodeIDs=array();
foreach ($ZipCodeArray as $v) {
$v = intval(trim($v));
if (strlen($v) == 5) {
array_push($ZipCodeIDs, $this->addZipCode($v));
} else {
echo "it isnt 5";
}
}
}
}
so what iam trying to do is make an array of an array. so this is how its supposed to look
Array
(
[1] => Array
(
[0] => 34
[1] => 31
[2] => 23
)
[2] => Array
(
[0] => 18
[1] => 4
[2] => 35
[3] => 1
)
)
i have tried numerous ways it doesnt work
basically i want it in this format VarName[ZoneNumbers][ZipCodeID]
so i can loop through it later on. so i can print like this $VarName[$n] then a array of all zipcodeID will print for Zone Number 1 in this case it will print 34,31,23
public function saveRateTemplateData($RateTemplateInfo)
{
$RateTemplateID = $RateTemplateInfo['id'];
$zones = array(); // you weren't using this so I'll use it to hold the data
for ($n = 1; $n <= $RateTemplateInfo['premium_zones']; $n++) {
$ZoneNum = 'zone' . $n;
// create an array under the zone number for holding the IDs
$zones[$n] = array();
$ZipCodeArray = explode(",",$_POST[$ZoneNum]);
foreach ($ZipCodeArray as $v) {
$v = (int) trim($v);
if (strlen($v) == 5) {
$zones[$n][] = $this->addZipCode($v);
} else {
// use exceptions for exceptional circumstances
throw new RuntimeException(sprintf('Invalid zone ID "%s"', $v));
}
}
}
return $zones;
}