Ожидайте, что неопределенное число будет числом: как преобразовать неопределенное число? - PullRequest
0 голосов
/ 27 октября 2019

Я пытался выяснить это в течение последних 3 дней, но не смог найти решение после выполнения нескольких тестов в Жасмин. Как это исправить, чтобы я мог пройти один из тестов «Ожидайте, что неопределенное будет числом», тогда как продолжительность фильмов должна быть числом?

Я знаю, что неопределенное происходит только в том случае, если свойство объекта нене существует или если объявленной переменной еще не присвоено значение.

Вот что я сделал с кодом

let movies = [
  {
    title: 'The Shawshank Redemption',
    year: '1994',
    director: 'Frank Darabont',
    duration: '2h 22min',
    genre: ['Crime', 'Drama'],
    rate: '9.3'
  },
  {
    title: 'The Godfather',
    year: '1972',
    director: 'Francis Ford Coppola',
    duration: '2h 55min',
    genre: ['Crime', 'Drama'],
    rate: '9.2'
  },
  {
    title: 'The Godfather: Part II',
    year: '1974',
    director: 'Francis Ford Coppola',
    duration: '3h 22min',
    genre: ['Crime', 'Drama'],
    rate: '9.0'
  }
]

function turnHoursToMinutes(minutesArr) {
  let durationArr = minutesArr.map(currentItem => {
    let stringtime = currentItem.duration;
    if (typeof stringtime === "string" && stringtime !== null && stringtime !== "" && stringtime !== undefined) {
    let strnumbers = stringtime.match(/\d+/g);
    let numbers = strnumbers.map(Number);
    let minutes = 0;
    if (stringtime.includes("h") && stringtime.includes("min")) {
      minutes = (numbers[0] * 60) + numbers[1];
    } else if (stringtime.includes("h")) {
      minutes = numbers[0] * 60;
    } else if (stringtime.includes("min")) {
      minutes = numbers[0];
    } 
    currentItem.duration = minutes;
    return {...currentItem};
    } else if (typeof stringtime === "number") {
      return currentItem.duration;
    } else if (typeof stringtime === "undefined") {
      return currentItem.duration = 0;
    }
  });

  return durationArr;

}
console.log(turnHoursToMinutes(movies));

Как видите, я попытался добавить свойство объекта, а также значение, подобное этому currentItem.duration = 0. Я думал, что смогу покрыть свои базы, если бы я написал этот код. Пожалуйста, дайте мне знать, что не так с моим кодом и как его подогнать.

Ответы [ 2 ]

0 голосов
/ 27 октября 2019

В вашей функции turnHoursToMinutes она обрабатывает 3 условия:

  1. currentItem.duration - строка, в этом случае она преобразует currentItem.duration в число и возвращает копию currentItem.
  2. currentItem.duration - это число, в этом случае функция просто возвращает значение currentItem.duration
  3. currentItem.duration не определено, в этом случае функция устанавливает значение currentItem.duration в 0 и возвращает 0

Заметили ли вы, что в двух последних случаях функция не возвращает весь объект, вместо этого она возвращает одно число?

Простое решение состоит в том, чтобы изменить результаты в двух последнихслучаи для возврата currentItem после установки продолжительности к соответствующему значению, если это необходимо.

0 голосов
/ 27 октября 2019

turnHoursToMinutes неправильно обрабатывает случай, когда значение duration уже равно Number или undefined. Посмотрите эту аннотированную версию вашей функции

function turnHoursToMinutes(minutesArr) {
  // >>> consider just returning the mapped Array
  return minutesArr.map(currentItem => {
    let stringtime = currentItem.duration;
    if (typeof stringtime === "string" &&
      stringtime !== null &&
      stringtime !== "" && stringtime !== undefined) {
      let strnumbers = stringtime.match(/\d+/g);
      let numbers = strnumbers.map(Number);
      let minutes = 0;
      if (stringtime.includes("h") && stringtime.includes("min")) {
        minutes = (numbers[0] * 60) + numbers[1];
      } else if (stringtime.includes("h")) {
        minutes = numbers[0] * 60;
      } else if (stringtime.includes("min")) {
        minutes = numbers[0];
      }
      currentItem.duration = minutes;

      // >>> no need for the spread and no need to return currentItem here
      // return {...currentItem};
    }

    // >>> no need for this case, because it's already a number
    // and that was what you wanted in the first place
    //!else if (typeof stringtime === "number") {

    // >>> this is why your test fails. You are still in the 'map' lambda
    // and should return currentItem, not the propery
    //!  return currentItem.duration;
    //!}
    //!else if (typeof stringtime === "undefined") {

    // >>> same: should've returned currentItem
    //!  return currentItem.duration = 0;
    //!}
    // >>> the above can be simplified to
    currentItem.duration = currentItem.duration || 0;
    // >>> now you've covered all, so return currentItem
    return currentItem;
  });
}

В любом случае, я позволил себе упростить ваш код. Этот рефакторинг извлекает код для определения числового значения (в минутах) duration, которое, в свою очередь, может быть использовано при (пере) отображении объекта фильмов.

const calcMinutesFromDurationString = str =>
  str ? String(str).split(" ")
          .reduce( (acc, val) => 
            acc + ( val.endsWith("h") ?  60 * parseInt(val)  : parseInt(val)), 0) 
      : 0;
    
const mapMoviesWithDurationInMinutes = item => 
  ( { ...item, duration: calcMinutesFromDurationString(item.duration) || 0 } );

console.log(getMovies().map(mapMoviesWithDurationInMinutes));

// ----------------
function getMovies() {
  return [
    {
      title: 'The Shawshank Redemption',
      year: '1994',
      director: 'Frank Darabont',
      duration: '2h 22min',
      genre: ['Crime', 'Drama'],
      rate: '9.3'
    },
    {
      title: 'The Godfather',
      year: '1972',
      director: 'Francis Ford Coppola',
      duration: '2h 55min',
      genre: ['Crime', 'Drama'],
      rate: '9.2'
    },
    {
      title: 'The Godfather: Part II',
      year: '1974',
      director: 'Francis Ford Coppola',
      duration: '3h 22min',
      genre: ['Crime', 'Drama'],
      rate: '9.0'
    },
    // added 1 without 'duration' 
    // actually the movie lasts 15 minutes :P
    {
      title: 'Capital Execution',
      year: '1903',
      director: 'Peter Elfelt',
      genre: ['Drama'],
      rate: 'n/a'
    },
    // added 1 with 'duration' = 'unknown' string
    {
      title: 'The Lamb',
      year: '1915',
      director: 'W. Christy Cabanne',
      genre: ['Comedy', 'Western'],
      rate: 'n/a',
      duration: 'unknown'
    },
    // added 1 with 'duration' = 71 (minutes)
    {
      title: 'Frankenstein',
      year: '1931',
      director: 'Robert Florey',
      genre: ['Drama', 'Horror'],
      rate: 'n/a',
      duration: 71
    },
  ];
}
.as-console-wrapper {
  max-height: 100% !important
}

Более того: теперь вы можете проверять конвертацию независимо

const calcMinutesFromDurationString = str =>
  str ? String(str).split(" ")
  .reduce((acc, val) =>
    acc + (val.endsWith("h") ? 60 * parseInt(val) : parseInt(val)), 0) || 0 :
  0;
  
console.log(`Converted values\n  calcMinutesFromDurationString("5h 0min") => ${
  calcMinutesFromDurationString("5h 0min")}\n  calcMinutesFromDurationString("") => ${
  calcMinutesFromDurationString("")}\n  calcMinutesFromDurationString("unknown") => ${
  calcMinutesFromDurationString("unknown")}\n  calcMinutesFromDurationString(65) => ${
  calcMinutesFromDurationString(65)}\n  calcMinutesFromDurationString("65min") => ${
  calcMinutesFromDurationString("65min")}\n  calcMinutesFromDurationString("1h") => ${
  calcMinutesFromDurationString("1h")}\n  calcMinutesFromDurationString() =>  ${
  calcMinutesFromDurationString()}\n  calcMinutesFromDurationString(null) => ${
  calcMinutesFromDurationString(null)}\n  calcMinutesFromDurationString("120") => ${
  calcMinutesFromDurationString("120")}`);
  
const isNumber = val => typeof val === "number" ? "yes" : "nope";
  
console.log(`Are we talking numbers here?
  calcMinutesFromDurationString("5h 0min") => ${
  isNumber(calcMinutesFromDurationString("5h 0min"))}
  calcMinutesFromDurationString("") => ${
  isNumber(calcMinutesFromDurationString(""))}
  calcMinutesFromDurationString("unknown") => ${
  isNumber(calcMinutesFromDurationString("unknown"))}
  calcMinutesFromDurationString(65) => ${
  isNumber(calcMinutesFromDurationString(65))}
  calcMinutesFromDurationString("65min") => ${
  isNumber(calcMinutesFromDurationString("65min"))}
  calcMinutesFromDurationString("1h") => ${
  isNumber(calcMinutesFromDurationString("1h"))}
  calcMinutesFromDurationString() =>  ${
  isNumber(calcMinutesFromDurationString())}
  calcMinutesFromDurationString(null) => ${
  isNumber(calcMinutesFromDurationString(null))}
  calcMinutesFromDurationString("120") => ${
  isNumber(calcMinutesFromDurationString("120"))}`);
.as-console-wrapper {
  max-height: 100% !important
}
...