【问题标题】:How do I push a parameter into a multiple nested array/object structure?如何将参数推送到多个嵌套数组/对象结构中?
【发布时间】:2019-09-13 17:11:43
【问题描述】:

给定以下数据库

DB = [
    {
        genre:'thriller', 
        movies:[
            {
                title:'the usual suspects', release_date:1999
            }
        ]},
        {
        genre:'commedy', 
        movies:[
            {
                title:'pinapple express', release_date:2008
            }
        ]}
]

我想检查其中是否存在流派和电影,如果没有则添加。

到目前为止,我有这个代码。唯一缺少的是,如果电影不存在(注释掉并加粗),则将(新)电影推送到类型索引处。

var moviesDB = function (array, genre, movie) {
    var x = []

    for (var i = 0; i < DB.length; i++) {
        x.push(DB[i].genre);
    }

    if(x.includes(genre) == false) {
        DB.push({genre: genre, movies: []});    
    } else {
        console.log("genre already here")
    }

    var y = []

    for (var i = 0; i < DB.length; i++) {
        DB[i].movies.forEach (function (object){
            y.push(object.title)
        })
    }

    if(y.includes(movie) == false) {
        //**push movie into the existing object.**
    } else {
        return `the movie the ${movie} is already in the database!`
    }

    return DB;
}

Sp moviesDB = function (DB, "drama", "A drama movie")应该添加一个新的流派对象(戏剧),并在电影数组中添加一个标题为“戏剧电影”的新对象。而moviesDB = function (DB, "commedy", "Scary movie") 应该只在现有的喜剧流派对象中添加一个带有电影标题的新对象。

DB = [
    {
        genre:'thriller', 
        movies:[
            {
                title:'the usual suspects', release_date:1999
            }
        ]},
        {
        genre:'commedy', 
        movies:[
            {
                title:'pinapple express', release_date:2008
            }
        ]}
]


var moviesDB = function (array, genre, movie) {
    var x = []

    for (var i = 0; i < DB.length; i++) {
        x.push(DB[i].genre);
    }

    if(x.includes(genre) == false) {
        DB.push({genre: genre, movies: []});    
    } else {
        console.log("genre already here")
    }

    var y = []

    for (var i = 0; i < DB.length; i++) {
        DB[i].movies.forEach (function (object){
            y.push(object.title)
        })
    }

    if(y.includes(movie) == false) {
        //**push movie into the existing object.**
    } else {
        return `the movie the ${movie} is already in the database!`
    }

    return DB;
}
console.log(moviesDB(DB, "drama", "A drama movie"))

【问题讨论】:

  • 尽可能保留代码结构,只帮助我突出显示的一行,因为这是我目前拥有的水平和技术。
  • 请点击edit然后[&lt;&gt;]创建一个minimal reproducible example - 很难猜出你如何调用你的moviesDB,看起来你在不应该循环的地方循环
  • 参数array 从未在您的函数中使用。 Imo 在该函数中出现的所有DB 都应替换为array,或者必须删除array 参数。
  • @3limin4t0r 当然,我在调用函数时使用它
  • 是的,您将它传递给函数,但从未在函数中实际使用它。尝试将moviesDB(DB, "drama", "A drama movie") 替换为moviesDB(undefined, "drama", "A drama movie"),您会看到产生相同的结果。

标签: javascript arrays loops object conditional-statements


【解决方案1】:

要达到预期,请将以下代码添加到注释部分

if(y.includes(movie) == false) {
        //**push movie into the existing object.**
      DB.forEach(v => {
        if(v.genre === genre){
          v.movies.push({title: movie})
        }
      })
    } 

说明:如果电影是现有对象,则循环数据库数组并检查流派并推送到电影列表

工作代码供参考

DB = [
    {
        genre:'thriller', 
        movies:[
            {
                title:'the usual suspects', release_date:1999
            }
        ]},
        {
        genre:'commedy', 
        movies:[
            {
                title:'pinapple express', release_date:2008
            }
        ]}
]


var moviesDB = function(DB, genre, movie) {
movie = typeof movie === 'object'? movie.title : movie; // to check whether movie parameter is string or object
    var x = []

    for (var i = 0; i < DB.length; i++) {
        x.push(DB[i].genre);
    }

    if(x.includes(genre) == false) {
        DB.push({genre: genre, movies: []});    
    } else {
        console.log("genre already here")
    }

    var y = []

    for (var i = 0; i < DB.length; i++) {
        DB[i].movies.forEach (function (object){
            y.push(object.title)
        })
    }

    if(y.includes(movie) == false) {
        //**push movie into the existing object.**
      DB.forEach(function(object) {
    if(object.genre === genre){
      object.movies.push({title: movie})
    }
  })
} else {
        return `the movie the ${movie} is already in the database!`
    }

    return DB;
}

console.log(moviesDB(DB, "drama", "A drama movie"))
console.log(moviesDB(DB, "commedy", "Scary movie"))
console.log(moviesDB(DB, 'commedy', 'pinapple express'))

codepen - https://codepen.io/nagasai/pen/oNvymeB?editors=1010

【讨论】:

  • 请分享失败的示例输入
  • 所以在调用movieDB方法时movieTitle可以作为'pinapple express'或{title:'pinapple express'}传递?
  • 更新了代码,添加了这一行,现在它应该适用于电影 = typeof 电影 === 'object'? movie.title : 电影; // 检查电影参数是字符串还是对象
  • @Stephan-thecurious,它是函数语句的箭头函数快捷方式,反正我已经更新了代码 - DB.forEach(function(object) { if(object.genre ===genre){ object.电影.push({title: 电影}) } }) }
  • 如果它总是 object ,那么只需使用 movie = movie.title
【解决方案2】:

我会使用下面的代码来解决这个问题,该代码易于理解和阅读,没有对没有太多经验的人来说可能“奇怪”的代码。

好吧,您可以首先循环对象以检查每个genre,如果其中一个与您要插入的对象匹配,则“选择”包含该类型的对象。如果没有找到流派,则创建一个新对象。

在拥有包含流派的对象(新的或已经存在的)之后,开始循环浏览该流派的电影,执行与流派相同的检查,除非您找到了电影title ,然后只返回一些东西,不要将电影推送到movies 列表。如果没有找到,则推送它。

看下面,看看代码是否通俗易懂(我在代码里面加了一些cmets)

let DB = [{
    genre: 'thriller',
    movies: [{
      title: 'the usual suspects',
      release_date: 1999
    }]
  },
  {
    genre: 'commedy',
    movies: [{
      title: 'pinapple express',
      release_date: 2008
    }]
  }
]

var moviesDB = function(array, genre, movie) {
  let selectedObj = null;

  //let's look for the genre, if exists
  for (let i = 0; i < array.length; i++) {
    let obj = array[i];
    if (obj.genre == genre) {
      selectedObj = obj;
      break
    }
  }

  //if the genre is not found, create a new one
  if (selectedObj == null) {
    selectedObj = {
      genre: genre,
      movies: []
    }
    array.push(selectedObj)
  }

  //let's check the movies of this genre
  let movies = selectedObj.movies
  for (let i = 0; i < movies.length; i++) {
    let mv = movies[i];
    if (mv.title == movie.title) {
      return "The movie '" + movie.title + "' already exists in genre: " + genre;
    }
  }

  //if the code didn't returned above, them insert new movie
  selectedObj.movies.push(movie)
  return "The movie '" + movie.title + "' was successfully inserted into genre: " + genre;
}


console.log(moviesDB(DB, 'commedy', {
  title: 'newOne',
  release_date: 2010
}))
console.log(moviesDB(DB, 'commedy', {
  title: 'pinapple express',
  release_date: 2008
}))

console.log(DB)

【讨论】:

  • 不休息有可能吗?目前不知道这个是什么概念
  • break 只是为了停止 for 循环继续......因为你已经找到了该类型的对象,所以没有必要继续循环,所以打破它停止并继续剩下的代码,(在更大的for循环中,它有助于提高性能,想象一下1000个对象,如果你在第二个位置找到了你需要的对象,为什么要循环更多998次?明白了吗?)
  • 是的,它会的。 (或者如果你有两个具有完全相同类型的对象,一个会覆盖另一个,但我不认为这里是这种情况)
  • 您的代码有效,但它比我目前可以应用的要高级一些。
【解决方案3】:

我会使用array.find 来确定该类型是否已经存在,然后推送新类型,或者确定现有类型中是否已经存在新标题并添加它。

const DB = [
    {
        genre:'thriller', 
        movies:[
            {
                title:'the usual suspects', release_date:1999
            }
        ]},
        {
        genre:'comedy', 
        movies:[
            {
                title:'pinapple express', release_date:2008
            }
        ]}
];


const addMovie = (db, genre, movie) => {
  const genreObject = db.find((dataItem) => dataItem.genre === genre);
  if(!genreObject){
    db.push({genre: genre, movies: [movie]});
  } else {
    const movieTitles = genreObject.movies.map((movie) => movie.title);
    if(!movieTitles.includes(movie.title)){
      genreObject.movies.push(movie);
    }
  }
}

addMovie(DB, "drama", {title: "pretend drama"});
addMovie(DB, "comedy", {title: "pretend comedy"});

console.log(DB);

【讨论】:

    【解决方案4】:

    据我了解这个问题,这是我想出的最简单的方法。代码是不言自明的,我在其中添加了 cmets

    const Database = [
      {
        genre: 'thriller',
        movies: [
          {
            title: 'the usual suspects',
            release_date: 1999
                }
            ]
      },
      {
        genre: 'comedy',
        movies: [
          {
            title: 'pinapple express',
            release_date: 2008
                }
            ]
      }
    ]
    
    const findOrAddMovie = ({ genre, movie }) => {
      // check if genre exists
      const hasGenre = Database.find(i => i.genre && i.genre === genre);
    
      if (!hasGenre) {
        // if genre doesn't exists, add it
        Database.push({ genre, movies: [] });
      }
    
      // map over the database 
      Database.map(item => {
        // only look in the genre we passed in 
        if (item.genre && item.genre === genre) {
          // find the movie by its title
          const thisMovie = item.movies.find(m => m.title === movie.title);
    
          if (!thisMovie) {
            // add movie if it doesn't exists
            // doing this here, so as to prevent 
            // another "map" call on "Database"
            item.movies.push({ ...movie });
          }
        }
      });
    
      //
      // just for references
      // 
      return Database;
    }
    
    console.log(
      findOrAddMovie({
        genre: "comedy",
        movie: {
          title: 'added movie 1',
          release_date: 2008
        }
      })
    );
    console.log(
      findOrAddMovie({
        genre: "thriller",
        movie: {
          title: 'added movie 2',
          release_date: 2008
        }
      })
    );
    console.log(
      findOrAddMovie({
        genre: "mygenre",
        movie: {
          title: 'added movie with genre',
          release_date: 2008
        }
      })
    );

    希望这会有所帮助!

    【讨论】:

    • 这非常优雅,但可能超出 OP 的范畴。
    【解决方案5】:

    您需要简化您的数据库 - 代码和数据库车要大大简化

    let DB = {
      'thriller': {
        movies: [{
          title: 'the usual suspects',
          release_date: 1999
        }]
      },
      'comedy': {
        movies: [{
          title: 'pinapple express',
          release_date: 2008
        }]
      }
    }
    
    var moviesDB = function(array, genre, title, release) {
      let g = DB[genre]
      if (!g) DB[genre] = {
        "movies": []
      }
      movies = DB[genre].movies
      const movie = {
        "title": title,
        "release_date": release
      }
      let obj = movies.find(o => o.title === movie.title);
      if (!obj) {
        movies.push(movie)
      } else {
        return `the movie the ${movie.title} is already in the database!`
      }  
      return DB;
    }
    moviesDB(DB, "drama", "A drama movie", 2019)
    moviesDB(DB, "drama", "A drama movie", 2019)
    moviesDB(DB, "thriller", "A thriller", 2019)
    console.log(DB)

    【讨论】:

    • 我不认为简化数据库是很多次的选择。
    • 所以因为你不这么认为,我的工作和改进的解决方案被否决了?
    • 是的。就是这样。
    猜你喜欢
    • 1970-01-01
    • 2021-10-28
    • 1970-01-01
    • 2021-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-22
    • 2019-03-28
    相关资源
    最近更新 更多