patternphpMinor
Take an array and return "n" elements, as evenly spaced as possible
Viewed 0 times
spacedelementsarraytakereturnpossibleandevenly
Problem
I get the following correct results from this code, but it seems incredibly clunky to me. Is there anything I could be doing more elegantly? The results can be imprecise - as long as it's the right number of returned elements, and the selection is mostly right.
```
$_5elements = array(1,2,3,4,5);
$_10elements = array(1,2,3,4,5,6,7,8,9,10);
$_14elements = array(1,2,3,4,5,6,7,8,9,10,11,12,13,14);
$_40elements = array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40);
$_140elements = array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140);
function spread_array($array = null, $target_array_length = 10) {
if ($array) {
$array_length = count($array);
if ($array_length > $target_array_length) {
$return = array();
$division = round( $array_length / $target_array_length );
krsort($array);
foreach ($array as $key => $value) {
if (($key === count($array) - 1 || $key % $division === 0) && count($return) ".print_r(spread_array($_5elements), true)."";
echo "".print_r(spread_array($_10elements), true)."";
echo "".print_r(spread_array($_14elements), true)."";
echo "".print_r(spread_array($_40elements, 20), true)."";
echo "".print_r(spread_array($_140elements), true)."";
/* Results
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
)
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
[5] => 6
[6] => 7
[7] => 8
[8] => 9
[9] => 10
)
Array
(
[0] => 5
[1] => 6
[2] =
```
$_5elements = array(1,2,3,4,5);
$_10elements = array(1,2,3,4,5,6,7,8,9,10);
$_14elements = array(1,2,3,4,5,6,7,8,9,10,11,12,13,14);
$_40elements = array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40);
$_140elements = array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140);
function spread_array($array = null, $target_array_length = 10) {
if ($array) {
$array_length = count($array);
if ($array_length > $target_array_length) {
$return = array();
$division = round( $array_length / $target_array_length );
krsort($array);
foreach ($array as $key => $value) {
if (($key === count($array) - 1 || $key % $division === 0) && count($return) ".print_r(spread_array($_5elements), true)."";
echo "".print_r(spread_array($_10elements), true)."";
echo "".print_r(spread_array($_14elements), true)."";
echo "".print_r(spread_array($_40elements, 20), true)."";
echo "".print_r(spread_array($_140elements), true)."";
/* Results
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
)
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
[5] => 6
[6] => 7
[7] => 8
[8] => 9
[9] => 10
)
Array
(
[0] => 5
[1] => 6
[2] =
Solution
Ding!!
I've got it!
So, I have been looking at this code for quite a while now, because I knew there had to be some ingenious way to do this. It seemed all to simple to need something of the opposite scale! And, after playing around, sure enough, I think I got it to it's best.
However! I'd hate to just give away the answer without a bit of some code critiquing beforehand. Shall we begin?...
I sure hope you didn't spend to long typing out those arrays. That'd would have been a bummer! Let's take advantage of a little resource, I like to call it the fill-numeric-array-o-matic. Switch that baby on, and bam, you get this beautiful babe:
Ain't she a beaut'?
Alright, next step! I see you countin' up the input array a couple times, good thing we know how to handle this! That's right, it needs to DRY out.
Feel free to replace all those nasty repetitions now!
After we've dried up that spill, let's knock off this arrow nonsense and whip up some clean lookin' code!
Watch ladies and gentlemen as we turn this snippet:
into this gorgeous girl piece of code!
I hope we all got to see this amazing transformation, the original having layers and layers,
Up next! The end is near, I promise! Before though, let's have a look at these formats and styles. Your code's fashion is really last year... Everyone's shopping at using 2014 standards.
Seriously though, applying and sticking to a style will benefit everyone. I highly recommend something such as PHP-FIG or the Zend Standards.
It's mostly just your naming conventions in this code that are goofy, and I have made some changes in my code below.
Last but not least, the algorithm! No offense, but your loop plus the conditions made everything so hard to follow. Debugging it to figure out what it did what gave me a headache. Good thing I have aspirin.
I found your choice of
Now, here's a list of requirements that must be achieved when we do the work:
I'm going to use a funky lookin'
How ya like them apples! Alrighty, let's see what I've done here:
Inside the loop, add to our output the value from
Reverse it to get the desired direction, and there ya have it!
Here's the full code that I came up with. Naming and all! I call this one: Make-sorted-and-spread-out-array-inator.
```
$arrayLength5 = range(1, 5);
$arrayLength10 = range(1, 10);
$arrayLength14 = range(1, 14);
$arrayLength40 = range(1, 40);
$arrayLength140 = range(1, 140);
function spreadOutArray(array $array, $targetOutputLength = 10) {
$originalArrayLength = count($array);
if ($originalArrayLength == 0) {
return false;
}
if ($originalArrayLength <= $targetOutputLength) {
return $array;
}
$output = [];
$interval = round($originalArrayLength / $targetOutputLength);
for ($index = $originalArrayLength - 1; count($output) < $targetOutpu
I've got it!
So, I have been looking at this code for quite a while now, because I knew there had to be some ingenious way to do this. It seemed all to simple to need something of the opposite scale! And, after playing around, sure enough, I think I got it to it's best.
However! I'd hate to just give away the answer without a bit of some code critiquing beforehand. Shall we begin?...
I sure hope you didn't spend to long typing out those arrays. That'd would have been a bummer! Let's take advantage of a little resource, I like to call it the fill-numeric-array-o-matic. Switch that baby on, and bam, you get this beautiful babe:
$_5elements = range(1, 5);
$_10elements = range(1, 10);
$_14elements = range(1, 14);
$_40elements = range(1, 40);
$_140elements = range(1, 140);Ain't she a beaut'?
Alright, next step! I see you countin' up the input array a couple times, good thing we know how to handle this! That's right, it needs to DRY out.
$array_length = count($array);Feel free to replace all those nasty repetitions now!
After we've dried up that spill, let's knock off this arrow nonsense and whip up some clean lookin' code!
Watch ladies and gentlemen as we turn this snippet:
if ($array) {
$array_length = count($array);
if ($array_length > $target_array_length) {
...
foreach (...) {
if (...) {
$return[] = $value;
}
}
$return = array_reverse($return);
} else {
$return = $array;
}
return $return;
}
return false;into this gorgeous girl piece of code!
$array_length = count($array);
if ($array_length == 0) {
return false;
}
if ($array_length <= $target_array_length) {
return $array;
}
*insert top secret algorithm here*
return array_reverse($output);I hope we all got to see this amazing transformation, the original having layers and layers,
ifs and elses all over! To now, a clean and concise workflow...Up next! The end is near, I promise! Before though, let's have a look at these formats and styles. Your code's fashion is really last year... Everyone's shopping at using 2014 standards.
Seriously though, applying and sticking to a style will benefit everyone. I highly recommend something such as PHP-FIG or the Zend Standards.
It's mostly just your naming conventions in this code that are goofy, and I have made some changes in my code below.
Last but not least, the algorithm! No offense, but your loop plus the conditions made everything so hard to follow. Debugging it to figure out what it did what gave me a headache. Good thing I have aspirin.
I found your choice of
krsort() unnecessary. Well, I've been able to completely remove this!Now, here's a list of requirements that must be achieved when we do the work:
- The amount of numbers returned MUST be equal to the number specified.
- The interval between numbers MUST be as even as possible throughout the list.
- The highest integer has priority in the output over the lowest numbers. (Assumed this one based on your output)
I'm going to use a funky lookin'
for loop to go through the array. It's going to look confusing at parts, but I'll do my best to make it worse clear things up!$output = [];
$ratio = round($array_length / $target_array_length);
for ($index = $array_length - 1; count($output) < $target_array_length; $index -= $ratio) {
$output[] = $array[$index];
}
return array_reverse($output);How ya like them apples! Alrighty, let's see what I've done here:
- Make a new
$outputarray to hold our output.
- Find the
$ratioat which we should go through the array at. This will cross off the evenly spaced requirement!
- We're going to set
$indexto one less than the original array's length. We do this so we can reference the highest index and not have an out of bounds error.
- Throughout the loop, check to make sure we have less in our output array than we want. If we have the right amount, break the loop. Cross off Req. #1!
- For each iteration, reduced our index by that ratio we came up with earlier.
Inside the loop, add to our output the value from
$array with the index that has been decreasing in the loop.Reverse it to get the desired direction, and there ya have it!
Here's the full code that I came up with. Naming and all! I call this one: Make-sorted-and-spread-out-array-inator.
```
$arrayLength5 = range(1, 5);
$arrayLength10 = range(1, 10);
$arrayLength14 = range(1, 14);
$arrayLength40 = range(1, 40);
$arrayLength140 = range(1, 140);
function spreadOutArray(array $array, $targetOutputLength = 10) {
$originalArrayLength = count($array);
if ($originalArrayLength == 0) {
return false;
}
if ($originalArrayLength <= $targetOutputLength) {
return $array;
}
$output = [];
$interval = round($originalArrayLength / $targetOutputLength);
for ($index = $originalArrayLength - 1; count($output) < $targetOutpu
Code Snippets
$_5elements = range(1, 5);
$_10elements = range(1, 10);
$_14elements = range(1, 14);
$_40elements = range(1, 40);
$_140elements = range(1, 140);$array_length = count($array);if ($array) {
$array_length = count($array);
if ($array_length > $target_array_length) {
...
foreach (...) {
if (...) {
$return[] = $value;
}
}
$return = array_reverse($return);
} else {
$return = $array;
}
return $return;
}
return false;$array_length = count($array);
if ($array_length == 0) {
return false;
}
if ($array_length <= $target_array_length) {
return $array;
}
*insert top secret algorithm here*
return array_reverse($output);$output = [];
$ratio = round($array_length / $target_array_length);
for ($index = $array_length - 1; count($output) < $target_array_length; $index -= $ratio) {
$output[] = $array[$index];
}
return array_reverse($output);Context
StackExchange Code Review Q#36983, answer score: 9
Revisions (0)
No revisions yet.