Можно ли не использовать для циклов в следующем фрагменте?
const states = [
{ a: 1 },
{ b: 1 },
{ b: 2, c: 1 }
];
const defaultState = {
a: 0,
b: 0,
c: 0
};
const getRange = prop => {
const range = [];
for (let i = 0; i < states.length; i += 1) {
let prevState;
for (let j = i - 1; j >= 0; j -= 1) {
prevState = states[j] && states[j][prop];
if (prevState) break;
}
range[i] = states[i][prop] || (prevState || defaultState[prop]);
}
return range;
};
getRange('a') // [1, 1, 1]
getRange('b') // [0, 1, 2]
getRange('c') // [0, 0, 1]
Он должен быть в JavaScript только без каких-либо других libs, я пытался немного поиграть с forEach() и some(), но не смог воспроизвести текущее поведение. Это касается изучения языковых целей.
const states = [
{ a: 1 },
{ b: 1 },
{ b: 2, c: 1 }
];
const defaultState = {
a: 0,
b: 0,
c: 0
};
const getRange = prop => {
return states.reduce((res, o, i) => {
res.push( o[prop] || res[i - 1] || defaultState[prop] );
return res;
}, []);
};
console.log(getRange('a')); // [1, 1, 1]
console.log(getRange('b')); // [0, 1, 2]
console.log(getRange('c')); // [0, 0, 1]
res
- массив результатов. Для каждого объекта o
в массиве states
мы нажимаем:
res.push( o[prop] || res[i - 1] || defaultState[prop] );
// or:
res[i] = o[prop] || res[i - 1] || defaultState[prop];
или:
o
state,res[i - 1]
) (предыдущее состояние),defaultState
. В моем коде reduce
замену внешнего for
вашего кода, res[i - 1]
заменяет внутреннее for
(поскольку нет необходимости цитировать, пока первый элемент не получит предыдущее состояние, которое мы уже знаем, это только на один шаг),
РЕДАКТИРОВАТЬ:
Чтобы лечить 0
как thruthy, используйте это:
res.push( (o[prop] || o[prop] == 0)? o[prop]: // if o[prop] is truthy or equal to 0 then use it
(res[i - 1] || res[i - 1] == 0)? res[i - 1]: // otherwise (o[prop] is neither truthy nor equal to 0) then if res[i - 1] is truthy or equal to 0 then use res[i - 1]
defaultState[prop] ); // otherwise just use the default value no matter whether it is truthy or not (that the point of default values anyway)
или:
res.push( !isNaN(o[prop])? o[prop]: // if o[prop] is a valid number use it
!isNaN(res[i - 1])? res[i - 1]: // otherwise, if res[i - 1] is a valid number then use it
defaultState[prop] ); // otherwise, use the default value
Весьма буквальный перевод - каждый цикл становится вызовом метода - кода будет
const getRange = defaultStats => state => prop => {
return states.map((state, i) => {
const prev = state.slice(0, i-1).reverse().find(s => s[prop]);
return state[prop] || prev[prop] || defaultState[prop];
});
};
prev = state.slice(0, i-1).reverse().find(s => s[prop])
, не проверили ваше решение, выбрали другое, я думаю, оно более элегантное ,
State 1: h: 100, w: 100 // output: h: 100, w: 100
State 2: h: 200 // output: h: 200, w: 100
State 3: w: 200 // output: h: 200, w: 200