i wants to separate an array with two groups (odd and even) sequentially. but when i try this:
why 4,8,6,2 instead of 2,4,6,8?
it is because you are modifying the same Array which you are looping through. to understand better, lets loop through your code
after
1st Loop: array: [1, 2, 3, 4, 5, 6, 7, 8, 9];
2nd loop: array: [1, 3, 4, 5, 6, 7, 8, 9, 2];
3rd loop: array: [1, 3, 5, 6, 7, 8, 9, 2, 4];
4th loop: array: [1, 3, 5, 7, 8, 9, 2, 4, 6];
5th loop: array: [1, 3, 5, 7, 9, 2, 4, 6, 8];
6th loop: array: [1, 3, 5, 7, 9, 4, 6, 8, 2];
7th loop: array: [1, 3, 5, 7, 9, 4, 8, 2, 6];
8th loop: array: [1, 3, 5, 7, 9, 4, 8, 6, 2];
9th loop: array: [1, 3, 5, 7, 9, 4, 8, 6, 2];
to separate out odd/even in an array,
we will have to filter out odd and even separately and push evenArray
in the end of oddArray
(filtered Array)
var input = [1, 2, 3, 4, 5, 6, 7, 8, 9];
input = input.sort((a, b)=> a-b); //to sort array if not sorted already
var evenArr = [];
input = input.filter(item => {
if (item % 2 != 0)
return true
else {
evenArr.push(item);
return false;
}
})
Array.prototype.push.apply(input, evenArr);
console.log(input);
Because you move every found even value to the end of the array:
0: 1 2 3 4 5 6 7 8 9 ^-------------v 1: 1 3 4 5 6 7 8 9 2 3 is not checked, because of the incremented index after splicing ^-----------v 2: 1 3 5 6 7 8 9 2 4 5 is not checked ^---------v 3: 1 3 5 7 8 9 2 4 6 7 is not checked ^-------v 4: 1 3 5 7 9 2 4 6 8 9 is not checked ^-----v 5: 1 3 5 7 9 4 6 8 2 ^---v 6: 1 3 5 7 9 4 8 2 6 ^-v 7: 1 3 5 7 9 4 8 6 2 | 8: 1 3 5 7 9 4 8 6 2
But, you do not check the value after the found even value, like the value 3
in line zero, because it is never checked and stays at this place, as well as other actually uneven values. You could try the whole again with all even at the beginning of the array, like
var array = [2, 4, 6, 8, 1, 3, 5, 7, 9];
for (var i = 0; i < array.length; i++) {
if (array[i] % 2 === 0) {
array.push(array.splice(i, 1)[0]);
console.log(i + ': ' + array.join(' '));
}
}
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You could use a length for checking and reduce the length for every found even value. In this case, the index stays at the value, because at the index is now the next element for checking.
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9],
i = 0,
l = array.length;
while (i < l) {
if (array[i] % 2 === 0) {
array.push(array.splice(i, 1)[0]);
l--;
continue;
}
i++;
}
console.log(array);
Or just sort.
By moving odd values to top and then sort by value.
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9];
array.sort((a, b) => b % 2 - a % 2 || a - b);
console.log(array);
The way you do it is so complicated. You can simply achieve that with array.prototype.filter
and array.prototype.concat
:
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
arr = arr.filter(e => e%2).concat(arr.filter(e => e%2 === 0));
console.log(arr);
why 4,8,6,2 instead of 2,4,6,8?
Basically when half of the iterations are done, it is re-processing the pushed items.
You need to change the for-loop as
for (var i = 0; i < arr.length/2; i++) {
if (arr[i]%2 == 0) {
arr.push(arr.splice(i, 1)[0]);
}
}
Demo
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
for (var i = 0; i < arr.length / 2; i++) {
if (arr[i] % 2 == 0) {
arr.push(arr.splice(i, 1)[0]);
}
}
console.log(arr);
Edit
And if the order of items is not always sorted, then you apart from sorting it first, you can reduce the length
variable.
var arr = [1, 2, 4, 3, 5, 6, 7, 8, 9];
var length = arr.length;
for (var i = 0; i < length; i++) {
console.log(i,arr[i]);
if (arr[i] % 2 == 0) {
arr.push(arr.splice(i, 1)[0]);
console.log("result ", arr)
length--;
i--;
}
}
console.log(arr)
I believe this can be covered by lodash _.partition
:
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var [odds, evens] = _.partition(arr, function(n) {
return n % 2;
});
console.log(_.concat(odds, evens));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Or even shorter:
_.groupBy(arr, function(n) {return (n % 2) ? 'odd' : 'even';})