моя программа очень проста - она должна сохранять фильмы в массив, а затем печатать их в формате JSON. Проблема в методе «содержит ()» (я думаю). Он хорошо работает с фильмом с одним именем, но возвращает null, если имя содержит пробелы. Вот код.
function movieDirectors(array) {
let movies = [];
class Movie {
constructor(name, director, date) {
this.name = name;
this.director = director;
this.date = date;
}
}
let contains = function (movieName) {
let movie = null;
movies.forEach(m => m.name === movieName ? movie = m : movie = null);
return movie;
}
for (let i = 0; i < array.length; i++) {
let command = array[i].split(' ');
if (command.includes('addMovie')) {
let name = command.slice(1, command.length).join(' ');
movies.push(new Movie(name, null, null));
} else if (command.includes('directedBy')) {
let name1 = command.slice(0, command.indexOf('directedBy')).join(' ');
if (contains(name1) !== null) {
let movie = contains(name1);
movie.director = command.slice(command.indexOf('directedBy') + 1, command.length).join(' ');
}
} else if (command.includes('onDate')) {
let name2 = command.slice(0, command.indexOf('onDate')).join(' ');
if (contains(name2) !== null) {
let movie = contains(name2);
movie.date = command.slice(command.indexOf('onDate') + 1, command.length).join(' ');
}
}
}
movies.forEach(m => m.director != null && m.name != null && m.date != null ? console.info(JSON.stringify(m)) : null);
}
movieDirectors([
'addMovie Fast and Furious',
'addMovie Godfather',
'Godfather directedBy Francis Ford Coppola',
'Godfather onDate 29.07.2018',
'Fast and Furious onDate 30.07.2018',
'Fast and Furious directedBy Rob Cohen']);
Вывод должен быть таким:
{"name":"Fast and Furious","date":"30.07.2018","director":"Rob Cohen"}
{"name":"Godfather","director":"Francis Ford Coppola","date":"29.07.2018"}
Я очень хорошо разбираюсь в языке JavaScript, и я буду благодарен за помощь в понимании этих тонкостей языка.
В моем университете есть система проверки домашних заданий, в которой есть тесты (например, этот), и поэтому я не могу изменить ввод.
Проблема в том, как вы сделали forEach
внутри contains()
.
Ты имел:
movies.forEach(m => m.name === movieName ? movie = m : movie = null);
Ваш массив movies
заполнен Fast and Furious
первым и Godfather
вторым. В первой итерации forEach он проверит Fast and Furious
и увидит, что он равен movieName
, поэтому movie = m
ваш код установит movie
с правильным объектом. Во второй итерации он запустит тот же тест с Godfather
и увидит, что он отличается от movieName
, поэтому movie = null
ваш код очистится movie
, и это ошибка. Вместо этого сделайте так, чтобы ваш код ничего не делал, когда m.name === movieName
ложно. Так:
movies.forEach(m => m.name === movieName ? movie = m : null);
Вот полный рабочий фрагмент:
function movieDirectors(array) {
let movies = [];
class Movie {
constructor(name, director, date) {
this.name = name;
this.director = director;
this.date = date;
}
}
let contains = function (movieName) {
let movie = null;
movies.forEach(m => m.name === movieName ? movie = m : null); // The problem was here
return movie;
}
for (let i = 0; i < array.length; i++) {
let command = array[i].split(' ');
if (command.includes('addMovie')) {
let name = command.slice(1, command.length).join(' ');
movies.push(new Movie(name, null, null));
} else if (command.includes('directedBy')) {
let name1 = command.slice(0, command.indexOf('directedBy')).join(' ');
if (contains(name1) !== null) {
let movie = contains(name1);
movie.director = command.slice(command.indexOf('directedBy') + 1, command.length).join(' ');
}
} else if (command.includes('onDate')) {
let name2 = command.slice(0, command.indexOf('onDate')).join(' ');
if (contains(name2) !== null) {
let movie = contains(name2);
movie.date = command.slice(command.indexOf('onDate') + 1, command.length).join(' ');
}
}
}
movies.forEach(m => m.director != null && m.name != null && m.date != null ? console.info(JSON.stringify(m)) : null);
}
movieDirectors([
'addMovie Fast and Furious',
'addMovie Godfather',
'Godfather directedBy Francis Ford Coppola',
'Godfather onDate 29.07.2018',
'Fast and Furious onDate 30.07.2018',
'Fast and Furious directedBy Rob Cohen']);
Спасибо за полное объяснение!
Поскольку ваша проблема в основном связана с разбором строк, вы можете решить ее с помощью таких регулярных выражений:
const input = [
'addMovie Fast and Furious',
'addMovie Godfather',
'Godfather directedBy Francis Ford Coppola',
'Godfather onDate 29.07.2018',
'Fast and Furious onDate 30.07.2018',
'Fast and Furious directedBy Rob Cohen'
];
const output = input.reduce((acc, cur) => {
const parseAddMovie = /^addMovie\s(.+)/.exec(cur);
if (parseAddMovie) {
const [, name] = parseAddMovie;
acc.push({ name });
return acc;
}
const parseDirectedBy = /(.+)\sdirectedBy\s(.+)/.exec(cur);
if (parseDirectedBy) {
const [, name, director] = parseDirectedBy;
const found = acc.find(x => x.name === name);
found && (found.director = director);
return acc;
}
const parseOnDate = /(.+)\sonDate\s(.+)/.exec(cur);
if (parseOnDate) {
const [, name, date] = parseOnDate;
const found = acc.find(x => x.name === name);
found && (found.date = date);
return acc;
}
}, []);
console.info(output);
Ожидается, что функция contains
остановится и вернется, когда найдет фильм с заданным названием.
Это будет работать:
let contains = function (movieName) {
return movies.find(m => m.name === movieName);
}
Я не понимаю, как вы можете разрешить именам фильмов иметь пробелы. Рассмотрите возможность изменения формата входного массива?