프로그래머스에서 <다리를 지나는 트럭> 풀다 막힌 문제인데
내 첫 식은 이랬다.
function solution(bridge_length, weight, truck_weights) {
let seconds = 0;
let onBridge = [ ...truck_weights ];
do {
let sumWeight = onBridge.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
if (sumWeight + waitings[0] <= weight) {
onBridge.push(waitings[0]);
waitings.shift();
} else {
offBridge.push(onBridge[0]);
onBridge.shift();
onBridge.push(waitings[0]);
waitings.shift();
}
seconds++;
// console.log("waitings");
// console.log(waitings);
// console.log("onBridge");
// console.log(onBridge);
// console.log("offBridge");
// console.log(offBridge);
// console.log(answer);
}
while (onBridge.length)
return seconds + bridge_length;
}
waitings 가 빈 배열로 남은 상태에도 push가 계속 일어나서 onBride에 계속 undefined 가 들어갔다
그리고 spread 연산자 쓰면서 시간을 꽤 많이 잡아먹게 되었다. 생각해 보니 함수 내 이용을 위해 truck_weights 변수에 선언되어 담기는 건데 또 다시 카피할 필요는 없다고 생각하여 뺐다.
결국 구글링해서 해답을 찾고 이렇게 바꾸었다.
function solution(bridge_length, weight, truck_weights) {
let seconds = 0;
let onBridge = Array.from({ length: bridge_length }, () => 0);
do {
onBridge.shift();
seconds++;
if (truck_weights.length) {
let sumWeight = onBridge.reduce((accumulator, currentValue) => accumulator + currentValue, 0); if (sumWeight + truck_weights[0] > weight) {
onBridge.push(0);
} else {
onBridge.push(truck_weights.shift());
}
}
}
while (onBridge.length)
return seconds;
}
아직까지도 reduce 함수 사용은 어렵다.
developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
모질라에 따르면 reducer 함수는 네 개의 파라미터를 받을 수 있다고 한다.
accumulator, currentValue, currentIndex, originalArray
accumulator 는 콜백의 반환값의 누적으로 첫번째 호출은 initialValue을 제공한 경우 initialValue 를 반환한다.
내 경우 initialValue는 0이다,
onBridge.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
콜백의 최초 호출 때 accumulator와 currentValue는 다음 두 가지 값 중 하나를 가질 수 있습니다. 만약 reduce() 함수 호출에서 initialValue를 제공한 경우, accumulator는 initialValue와 같고 currentValue는 배열의 첫 번째 값과 같습니다. initialValue를 제공하지 않았다면, accumulator는 배열의 첫 번째 값과 같고 currentValue는 두 번째와 같습니다.
참고: initialValue를 제공하지 않으면, reduce()는 인덱스 1부터 시작해 콜백 함수를 실행하고 첫 번째 인덱스는 건너 뜁니다. initialValue를 제공하면 인덱스 0에서 시작합니다.
object 로 이뤄진 배열의 합의 경우 예제는 이렇다.
var initialValue = 0;
var sum = [{x: 1}, {x:2}, {x:3}].reduce(
(accumulator, currentValue) => accumulator + currentValue.x
,initialValue
);
console.log(sum) // logs 6
이건 나중에 사용해봐야겠다.
reduce를 이용한다면 괜한 변수 먼저 선언해서 for 문 돌려 더해줄 필요도 없지 않은가...!
----- 2021-04-22 추가로 좋은 방법을 또 익혀서 추가한다.
언제 사용할지는 모르겠지만
var flattened = [[0, 1], [2, 3], [4, 5]].reduce(
function(accumulator, currentValue) {
return accumulator.concat(currentValue);
},
[]
);
// 펼친 결과: [0, 1, 2, 3, 4, 5]
var flattened = [[0, 1], [2, 3], [4, 5]].reduce(
( accumulator, currentValue ) => accumulator.concat(currentValue),
[]
);
이렇게 중첩배열을 하나의 배열로 만들어줄 수 있다고 한다.
(모든 예제는 모질라 출처이다.)
객체 내 인스턴스 세기
var names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];
var countedNames = names.reduce(function (allNames, name) {
if (name in allNames) {
allNames[name]++;
}
else {
allNames[name] = 1;
}
return allNames;
}, {});
// countedNames is:
// { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }
속성으로 객체 분류하기 예제 (이거는 플젝에 썼었다!)
var people = [
{ name: 'Alice', age: 21 },
{ name: 'Max', age: 20 },
{ name: 'Jane', age: 20 }
];
function groupBy(objectArray, property) {
return objectArray.reduce(function (acc, obj) {
var key = obj[property];
if (!acc[key]) {
acc[key] = [];
}
acc[key].push(obj);
return acc;
}, {});
}
var groupedPeople = groupBy(people, 'age');
// groupedPeople is:
// {
// 20: [
// { name: 'Max', age: 20 },
// { name: 'Jane', age: 20 }
// ],
// 21: [{ name: 'Alice', age: 21 }]
// }
내가 쓴 방식은 이럼 (예제의 활용)
var people = [
{ name: 'Alice', age: 21, gender: "female" },
{ name: 'Max', age: 20, gender: "male" },
{ name: 'Jane', age: 20, gender: "female" }
];
var genderGroup = people.reduce((rv, { gender, ...rest }) => {
const key = `${gender}`;
rv[key] = rv[key] || [];
rv[key].push(rest);
rv[key].sort((a, b) => a["age"] - b["age"]);
return rv;
}, {})
from도 새로 발견하게 되었다,
developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from
모질라에 따르면 얕게 복사한 새 배열을 만들어준다고 한다.
// Generate a sequence of numbers
// Since the array is initialized with `undefined` on each position,
// the value of `v` below will be `undefined`
Array.from({length: 5}, (v, i) => i);
// [0, 1, 2, 3, 4]
파라미터로 들어갈 배열이 없으므로 사용할 value 도 없으니 v 는 undefined으로 나올 것이고 return 값은 인덱스로 나오게 한다는 말이다.
Array.from({ length: bridge_length }, () => 0);
내 코드는 이걸 응용한 건데 위 코드는 애초에 parameter로는 아무것도 받지 않고 bride_length 개수만 맞춰 0으로 구성된 배열을 만든 것이다.
참고로 Array.from()을 이용하면 문자열을 문자마다 쪼개 배열을 만드는 것도 split("") 없이 가능하다.
var foo = Array.from("foo");
이것과
var foo = "foo".split("")
이것의 결과값은 결국 같다.
그래서 Array.from()은 array-like 의 값을 받는다고 했나보다.
위 모질라에서 나온 Array.from() 을 이용하여 수열 배열 만드는 법...
// Sequence generator function (commonly referred to as "range", e.g. Clojure, PHP etc)
const range = (start, stop, step) => Array.from({ length: (stop - start) / step + 1}, (_, i) => start + (i * step));
// Generate numbers range 0..4
range(0, 4, 1);
// [0, 1, 2, 3, 4]
// Generate numbers range 1..10 with step of 2
range(1, 10, 2);
// [1, 3, 5, 7, 9]
이것은 같은 range 함수로 알파멧 숫자..!
// Generate the alphabet using Array.from making use of it being ordered as a sequence
range('A'.charCodeAt(0), 'Z'.charCodeAt(0), 1).map(x => String.fromCharCode(x));
// ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
오늘도 열공열공...!
'Javascript' 카테고리의 다른 글
[Javascript] string 공백 지우기, Removing whitespace (0) | 2021.09.01 |
---|---|
[Javascript] Optional Chaining ( ?.) (0) | 2021.04.07 |
[Javascript] Array 중복 제거 - Set 사용 (1) | 2021.03.31 |
[Javascript] Array.prototype.some(), Array.prototype.every() (0) | 2021.03.31 |
[Javascript] if, if~else if~else, for, while, forEach (0) | 2021.03.31 |