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

时间:2017-10-17 13:58:57

标签: javascript arrays json node.js merge

我想合并两个包含有关电影信息的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%"
}]

4 个答案:

答案 0 :(得分:1)

您实际需要的是组合两个数组,然后过滤它们以删除重复数据:

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;
    });
};

答案 1 :(得分:0)

这样的事情应该有用。

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)));
    }

答案 2 :(得分:0)

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

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]);
};

答案 3 :(得分:0)

您可以使用array#reduce在两个阵列中制作独特的电影。

&#13;
&#13;
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));
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
&#13;
&#13;