Преобразование циклов for в forEach / map / some ... и т. Д.

1

Можно ли не использовать для циклов в следующем фрагменте?

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(), но не смог воспроизвести текущее поведение. Это касается изучения языковых целей.

  • 2
    Что делает этот код?
  • 0
    @ibrahimmahrir В каждом штате могут быть реквизиты, каждый реквизит может меняться, реквизиты, которые не были изменены, должны оставаться неизменными и не теряться при переходе в новое состояние. Пример: 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
Показать ещё 3 комментария
Теги:

2 ответа

1
Лучший ответ

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
  • 0
    Объясни, что ты делаешь. Дампы кода не являются хорошими ответами.
  • 0
    @Slim Я объяснял, когда вы публиковали этот комментарий.
Показать ещё 14 комментариев
1

Весьма буквальный перевод - каждый цикл становится вызовом метода - кода будет

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];
  });
};
  • 0
    Это блестящая строка prev = state.slice(0, i-1).reverse().find(s => s[prop]) , не проверили ваше решение, выбрали другое, я думаю, оно более элегантное ,
  • 0
    @ user5470921… и более того, более производительный, да :-)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню