Daily Codewars #24
Question
codewars link
Write an algorithm that takes an array and moves all of the zeros to the end, preserving the order of the other elements.
moveZeros([false,1,0,1,2,0,1,3,"a"]) // returns[false,1,1,2,1,3,"a",0,0]
My Solution
//success code var moveZeros = function (arr) { for(var i = arr.length; i--;) { if(arr[i] === 0) { arr.splice(i, 1); arr.push(0); } } return arr; }
//babo code arr.map(function(item, i) { if(item===0){ arr.splice(i, 1); arr.push(0); } });
처음에는 두번째 코드처럼 map으로 짰다. 하지만 이는 배열에서 0을 삭제할때마다 index가 꼬이는 문제가 있어서 간단한 for loop를 돌렸다.
@jakber’s Solution
var moveZeros = function (arr) { return arr.filter(function(x) {return x !== 0}).concat(arr.filter(function(x) {return x === 0;})); }
이야아… filter로 0이 아닌것과 0인걸 나누어서 concat했다.
저도 매일 같이 해 보니까 재밌네요 ㅋ.. 이번에도 다른 방법으로 풀어봤는데, 일단 jakber의 코드의 경우 두 번의 루프를 도는거라서 성능이슈가 있을 수 있어서 루프 한 번 도는 것으로 하면.. (단 lodash 의 지연실행 같은 방법을 사용하면 jakber의 방법이 가장 나을 수 있습니다)
function moveZerosOneLoop (arr) {
return arr.reduceRight(function (result, elem) {
if (elem === 0) {
result.push(elem);
} else {
result.unshift(elem)
}
return result;
}, []);
}
근데, unshift 의 경우 위에 사용하신 slice 등과 같이 push 에 비해 퍼포먼스가 조금 떨어집니다. 따라서 굉장히 많은 데이터를(수만개..^^) 처리하고자 한다면, 아래와 같이하면 조금 더 성능을 끌어올릴 수 있을 것 같네요.
function moveZerosFaster (arr) {
var zeros = [], others = [];
arr.forEach(function (elem) {
if (elem === 0) {
zeros.push(elem);
} else {
others.push(elem)
}
});
return others.concat(zeros);
}