如何合并唯一的两个JSON文件?

我想合并两个包含电影信息的JSON文件。 这些文件有一些共同的项目。 我想写第三个文件,其中包括所有的电影,而不重复他们。

以下是我到目前为止:

const fs = require('fs'); const path = require('path'); const readMovies1 = () => { return new Promise((resolve, reject) => { fs.readFile(path.join(__dirname,'../models/movies.json'), 'utf8', (err, data1) => { if(err) reject(err); let data = JSON.parse(data1); resolve(data); }); }); }; const readMovies2 = (data1) => { return new Promise((resolve, reject) =>{ fs.readFile(path.join(__dirname,'../models/movies2.json'), 'utf8', (err, data) => { if(err) reject(err); data = JSON.parse(data); resolve([data1,data]); }); }); }; const merging = (data1, data2) => { var args = arguments; var hash = {}; var arr = []; for (var i = 0; i < args.length; i++) { for (var j = 0; j < args[i].length; j++) { if (hash[args[i][j]] !== true) { arr[arr.length] = args[i][j]; hash[args[i][j]] = true; } } } return arr; }; readMovies1() .then(readMovies2) .catch((err) => console.error(err)) .then((data) => console.log(merging(data[0],data[1]))) .catch((err) => console.error(err)); 

但是控制台输出给了我这个:

  [ undefined, '/', 'U', 's', 'e', 'r', 'g', 'o', 'n', 'z', 'P', 'j', 'c', 't', 'J', 'S', 'a', 'd', 'm', '-', 'v', 'i', 'l', 'b', '.' ] 

我在堆栈溢出的一个问题中发现了合并函数,但是它合并了一个数组数组,并且正在合并对象数组。 我不知道这是否与我的问题有关。

这是我的一个源文件(其他的遵循相同的模式,但有一些其他的电影):

 [{ "title": "Spider-Man: Homecoming", "usersScore": "92%", "criticsScore": "89%" }, { "title": "Girls Trip", "usersScore": "89%", "criticsScore": "83%" }, { "title": "Captain Underpants: The First Epic Movie (Captain Underpants)", "usersScore": "87%", "criticsScore": "62%" }, { "title": "Guardians of the Galaxy Vol. 2", "usersScore": "82%", "criticsScore": "88%" }, { "title": "Wonder Woman", "usersScore": "92%", "criticsScore": "89%" }, { "title": "First They Killed My Father", "usersScore": "88%", "criticsScore": "83%" }, { "title": "Baby Driver", "usersScore": "93%", "criticsScore": "87%" }, { "title": "Demon", "usersScore": "91%", "criticsScore": "56%" }, { "title": "The Music of Strangers: Yo-Yo Ma and the Silk Road Ensemble", "usersScore": "84%", "criticsScore": "85%" }, { "title": "Colossal", "usersScore": "80%", "criticsScore": "59%" }, { "title": "Certain Women", "usersScore": "92%", "criticsScore": "51%" }, { "title": "Godzilla Resurgence (Shin Godzilla)", "usersScore": "84%", "criticsScore": "73%" }, { "title": "My Cousin Rachel", "usersScore": "76%", "criticsScore": "47%" }, { "title": "The Meyerowitz Stories (New and Selected)", "usersScore": "93%", "criticsScore": "84%" }, { "title": "Raw", "usersScore": "90%", "criticsScore": "77%" }, { "title": "The Wedding Plan", "usersScore": "86%", "criticsScore": "65%" }, { "title": "Maudie", "usersScore": "88%", "criticsScore": "92%" }, { "title": "Heal the Living (Réparer les vivants)", "usersScore": "90%", "criticsScore": "70%" }, { "title": "Lady Macbeth", "usersScore": "89%", "criticsScore": "72%" }, { "title": "The Exception (The Kaiser's Last Kiss)", "usersScore": "76%", "criticsScore": "67%" }, { "title": "Citizen Jane: Battle for the City", "usersScore": "94%", "criticsScore": "61%" }, { "title": "The Beguiled", "usersScore": "78%", "criticsScore": "50%" }, { "title": "The Big Sick", "usersScore": "98%", "criticsScore": "89%" }, { "title": "The Little Hours", "usersScore": "77%", "criticsScore": "53%" }, { "title": "A Ghost Story", "usersScore": "91%", "criticsScore": "66%" }, { "title": "The Hero", "usersScore": "77%", "criticsScore": "64%" }, { "title": "Megan Leavey", "usersScore": "84%", "criticsScore": "83%" }, { "title": "Band Aid", "usersScore": "85%", "criticsScore": "73%" }, { "title": "It Comes At Night", "usersScore": "89%", "criticsScore": "43%" }, { "title": "The Midwife (Sage femme)", "usersScore": "86%", "criticsScore": "82%" }, { "title": "Brawl in Cell Block 99", "usersScore": "93%", "criticsScore": "75%" }, { "title": "Gerald's Game", "usersScore": "89%", "criticsScore": "78%" }] 

你真正需要的是将两个数组组合,然后过滤它们以删除重复项:

 const merge = (data1, data2) => { // keeps track of already existing titles to avoid duplicates let existingIndexes = {}; // check the the arguments to make sure the code does not break data1 = data1 instanceof Array ? data1 : []; data2 = data2 instanceof Array ? data2 : []; // return a concatenated and filtered copy result return data1.concat(data2).filter((movie) => { if (existingIndexes.hasOwnProperty(movie.title)) { existingIndexes[movie.title] = true; return true; } return false; }); }; 

我最喜欢处理从数组中删除重复的方法是使用一个对象作为字典,然后转换回数组。 这不是最有效的方法,但我喜欢代码最终变得简单。 我们需要一些方法来跟踪重复的值(在这种情况下你的电影标题),和对象很容易处理这个给我们。

 const merge = (key, arr1, arr2) => { // Should probably check our parameters, but I'm leaving it out // Our "dictionary" that will help prevent duplicates by using keys let dictionary = {}; // Values in arr2 will overwrite values in arr1 if there is a duplicate arr1.concat(arr2).forEach(item => { dictionary[item[key]] = item; // To always keep the first value, you could replace the previous line with this: // dictionary[item[key]] = dictionary[item[key]] || item; }); return Object.keys(dictionary).map(i => dictionary[i]); }; 

像这样的东西应该工作。

 const getTitles = movies => movies.map(movie => movie.title); const merge = (data1, data2) => { const titles1 = getTitles(data1); return data1.concat(data2.filter(movie => !titles1.includes(movie.title))); } 

你可以使用array#reduce在你的数组中获得唯一的影片。

 var data1 = [{"title":"Spider-Man: Homecoming","usersScore":"92%","criticsScore":"89%"},{"title":"Girls Trip","usersScore":"89%","criticsScore":"83%"},{"title":"Captain Underpants: The First Epic Movie (Captain Underpants)","usersScore":"87%","criticsScore":"62%"},{"title":"Guardians of the Galaxy Vol. 2","usersScore":"82%","criticsScore":"88%"},{"title":"Wonder Woman","usersScore":"92%","criticsScore":"89%"},{"title":"First They Killed My Father","usersScore":"88%","criticsScore":"83%"},{"title":"Baby Driver","usersScore":"93%","criticsScore":"87%"},{"title":"Demon","usersScore":"91%","criticsScore":"56%"},{"title":"The Music of Strangers: Yo-Yo Ma and the Silk Road Ensemble","usersScore":"84%","criticsScore":"85%"},{"title":"Colossal","usersScore":"80%","criticsScore":"59%"},{"title":"Certain Women","usersScore":"92%","criticsScore":"51%"},{"title":"Godzilla Resurgence (Shin Godzilla)","usersScore":"84%","criticsScore":"73%"},{"title":"My Cousin Rachel","usersScore":"76%","criticsScore":"47%"},{"title":"The Meyerowitz Stories (New and Selected)","usersScore":"93%","criticsScore":"84%"},{"title":"Raw","usersScore":"90%","criticsScore":"77%"},{"title":"The Wedding Plan","usersScore":"86%","criticsScore":"65%"},{"title":"Maudie","usersScore":"88%","criticsScore":"92%"},{"title":"Heal the Living (Réparer les vivants)","usersScore":"90%","criticsScore":"70%"},{"title":"Lady Macbeth","usersScore":"89%","criticsScore":"72%"},{"title":"The Exception (The Kaiser's Last Kiss)","usersScore":"76%","criticsScore":"67%"},{"title":"Citizen Jane: Battle for the City","usersScore":"94%","criticsScore":"61%"},{"title":"The Beguiled","usersScore":"78%","criticsScore":"50%"},{"title":"The Big Sick","usersScore":"98%","criticsScore":"89%"},{"title":"The Little Hours","usersScore":"77%","criticsScore":"53%"},{"title":"A Ghost Story","usersScore":"91%","criticsScore":"66%"},{"title":"The Hero","usersScore":"77%","criticsScore":"64%"},{"title":"Megan Leavey","usersScore":"84%","criticsScore":"83%"},{"title":"Band Aid","usersScore":"85%","criticsScore":"73%"},{"title":"It Comes At Night","usersScore":"89%","criticsScore":"43%"},{"title":"The Midwife (Sage femme)","usersScore":"86%","criticsScore":"82%"},{"title":"Brawl in Cell Block 99","usersScore":"93%","criticsScore":"75%"},{"title":"Gerald's Game","usersScore":"89%","criticsScore":"78%"}], data2 = [{ "title": "The Midwife (Sage femme)","usersScore": "86%","criticsScore": "82%"}, {"title": "Brawl in Cell Block 99","usersScore": "93%", "criticsScore": "75%"}, {"title": "Gerald's Game","usersScore": "89%","criticsScore": "78%" }]; const merging = (data1, data2) => { let unique = data1.concat(data2).reduce((map, movie) => { return map[movie.title] = movie, map; }, Object.create(null)); return Object.values(unique); }; console.log(merging(data1,data2)); 
 .as-console-wrapper { max-height: 100% !important; top: 0; }