简体   繁体   English

javascript-合并,合并,转换2个不同的对象数组

[英]javascript - merge, combine, transform 2 different arrays of Objects

I can't figure it out how to transform and combine 2 arrays of object. 我无法弄清楚如何转换和合并2个对象数组。

I have this 2 arrays of objects: 我有这2个对象数组:

const selectedCourse = [
    {
      "courseType": [5],
      "id": 26,
      "title": "Apple Tart with Apricot Glaze",
  },
  {
    "courseType": [3],
    "id": 16,
    "title": "Classic Caesar Salad",
},
{
  "courseType": [1,2],
  "id": 10,
  "title": "Lobster Bisque",
},
{
  "courseType": [3],
  "id": 16,
  "title": "Classic Caesar Salad",
},
]

const courseTypes = [
{name: "Hors d'oeuvres", id: 0},
 {name: "Soup", id: 1},
 {name: "Fish", id: 2},
 {name: "Salad", id: 3},
 {name: "Main course", id: 4},
 {name: "Dessert", id: 5}
]

The courseType property inside the first JSON is an array of numbers that corresponds to courseTypes index and property id in the second JSON. 第一个JSON中的courseType属性是一个数字数组,与第二个JSON中的courseTypes索引和属性ID相对应。

The result for this case should be this: 这种情况的结果应为:

const result = [
  {
    courseType: 1,
    courseName: "Soup",
    courses: [
      {
        "courseType": [1,2],
        "id": 10,
        "title": "Lobster Bisque",
      }      
    ]
  },
  {
    courseType: 3,
    courseName: "Salad",
    courses: [
      {
        "courseType": [1,2],
        "id": 10,
        "title": "Lobster Bisque",
      }      
    ]
  },
  {
    courseType: 3,
    courseName: "Fish",
    courses: [
      {
        "courseType": [3],
        "id": 16,
        "title": "Classic Caesar Salad",
      },
      {
        "courseType": [3],
        "id": 16,
      },      
    ]
  },
  {
    courseType: 5,
    courseName: "Main course",
    courses: [
      {
        "courseType": [5],
        "id": 26,
        "title": "Apple Tart with Apricot Glaze",
      }
    ]
  }
]

The expected result have to combine the 2 arrays by filtering by courseType property. 预期的结果必须通过按CourseType属性进行过滤来合并两个数组。

Assuming, you want all items with selectedCourse , you could take a Map and collect all courses and later greate a new array out of the found values. 假设,您希望所有具有selectedCourse项目,都可以获取一个Map并收集所有课程,然后从找到的值中扩充一个新数组。

This solution includes Fish as well. 此解决方案还包括Fish

 const selectedCourse = [{ courseType: [5], id: 26, title: "Apple Tart with Apricot Glaze" }, { courseType: [3], id: 16, title: "Classic Caesar Salad" }, { courseType: [1, 2], id: 10, title: "Lobster Bisque" }, { courseType: [3], id: 16, title: "Classic Caesar Salad" }], courseTypes = [{ name: "Hors d'oeuvres", id: 0 }, { name: "Soup", id: 1 }, { name: "Fish", id: 2 }, { name: "Salad", id: 3 }, { name: "Main course", id: 4 }, { name: "Dessert", id: 5 }], map = selectedCourse.reduce((m, o) => o.courseType.reduce((n, id) => n.set(id, [...(n.get(id) || []), o]), m), new Map), result = courseTypes.reduce( (r, { name: courseName, id: courseType }) => (map.get(courseType) || []).reduce((s, courses) => s.concat({ courseType, courseName, courses }), r), [] ); console.log(result); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

You could use map and filter like this: 您可以像这样使用mapfilter

 const selectedCourse = [ { "courseType": [5], "id": 26, "title": "Apple Tart with Apricot Glaze", }, { "courseType": [3], "id": 16, "title": "Classic Caesar Salad", }, { "courseType": [1,2], "id": 10, "title": "Lobster Bisque", }, { "courseType": [3], "id": 16, "title": "Classic Caesar Salad", }, ] const courseTypes = [ {name: "Hors d'oeuvres", id: 0}, {name: "Soup", id: 1}, {name: "Fish", id: 2}, {name: "Salad", id: 3}, {name: "Main course", id: 4}, {name: "Dessert", id: 5} ]; const result = courseTypes.map(courseType => ({ courseType: courseType.id, courseName: courseType.name, courses: selectedCourse.filter(course => course.courseType.includes(courseType.id)) })).filter(extended => extended.courses.length); console.log(JSON.stringify(result, null, 2)); 

Explanation: 说明:

courseTypes.map iterates over your second input array and for each type it finds in selectedCourse which courses match with that particular type. courseTypes.map遍历第二个输入数组,并为它在selectedCourse中找到的每种类型与该特定类型匹配的课程进行迭代。

It uses .filter to collect those matches. 它使用.filter收集那些匹配项。 The filter callback uses includes to determine if there is a match -- it returns a boolean, exactly what the filter callback expects as return value. filter回调函数使用includes来确定是否存在匹配项-它返回一个布尔值,该布尔值恰好是过滤器回调函数期望的返回值。

This filtered array is then added to an object literal that also defines the other two properties courseType and courseName . 然后,将这个过滤后的数组添加到一个对象常量中,该对象常量还定义了其他两个属性courseTypecourseName That new object is what the course type is mapped to. 该新对象就是课程类型所映射的对象。 courseTypes.map returns an array of those objects. courseTypes.map返回这些对象的数组。

Finally that result may have entries that have an empty courses array. 最后,该结果可能包含具有空courses数组的条目。 Those are filtered out with another call to .filter . 这些被另一个调用.filter过滤掉。 If the length of that courses array is non zero, the object is kept, otherwise it is kicked out of the result. 如果该courses数组的length不为零,则保留该对象,否则将其踢出结果。

For older browsers 对于较旧的浏览器

Here is the same code made compatible with older browsers (no arrow functions, no includes , which were introduced in ES2015): 这是与较旧的浏览器兼容的相同代码(没有箭头功能,没有includes ,这是ES2015中引入的):

 const selectedCourse = [ { "courseType": [5], "id": 26, "title": "Apple Tart with Apricot Glaze", }, { "courseType": [3], "id": 16, "title": "Classic Caesar Salad", }, { "courseType": [1,2], "id": 10, "title": "Lobster Bisque", }, { "courseType": [3], "id": 16, "title": "Classic Caesar Salad", }, ] const courseTypes = [ {name: "Hors d'oeuvres", id: 0}, {name: "Soup", id: 1}, {name: "Fish", id: 2}, {name: "Salad", id: 3}, {name: "Main course", id: 4}, {name: "Dessert", id: 5} ]; const result = courseTypes.map(function (courseType) { return { courseType: courseType.id, courseName: courseType.name, courses: selectedCourse.filter(function (course) { return course.courseType.indexOf(courseType.id) > -1; }) }; }).filter(function (extended) { return extended.courses.length; }); console.log(JSON.stringify(result, null, 2)); 

while "trincot" code is work fine for chrome and Mozila but it will not work in IE edge and IE 10 and below you need to convert it in pure javascript. 虽然“ trincot”代码在chrome和Mozila上工作正常,但在IE edge和IE 10及以下版本中将无法正常工作,您需要将其转换为纯JavaScript。 below is code which will work in all browser. 以下是适用于所有浏览器的代码。

if (!Array.prototype.includes) {
   Object.defineProperty(Array.prototype, 'includes', {
   value: function(searchElement, fromIndex) {

  if (this == null) {
    throw new TypeError('"this" is null or not defined');
  }

  // 1. Let O be ? ToObject(this value).
  var o = Object(this);

  // 2. Let len be ? ToLength(? Get(O, "length")).
  var len = o.length >>> 0;

  // 3. If len is 0, return false.
  if (len === 0) {
    return false;
  }

  // 4. Let n be ? ToInteger(fromIndex).
  //    (If fromIndex is undefined, this step produces the value 0.)
  var n = fromIndex | 0;

  // 5. If n ≥ 0, then
  //  a. Let k be n.
  // 6. Else n < 0,
  //  a. Let k be len + n.
  //  b. If k < 0, let k be 0.
  var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);

  function sameValueZero(x, y) {
    return x === y || (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y));
  }

  // 7. Repeat, while k < len
  while (k < len) {
    // a. Let elementK be the result of ? Get(O, ! ToString(k)).
    // b. If SameValueZero(searchElement, elementK) is true, return true.
    if (sameValueZero(o[k], searchElement)) {
      return true;
    }
    // c. Increase k by 1. 
    k++;
  }

  // 8. Return false
  return false;
    }
  });
}
var selectedCourse = [{ "courseType": [5], "id": 26, "title": "Apple Tart with Apricot Glaze" }, { "courseType": [3], "id": 16, "title": "Classic Caesar Salad" }, { "courseType": [1, 2], "id": 10, "title": "Lobster Bisque" }, { "courseType": [3], "id": 16, "title": "Classic Caesar Salad" }];
var courseTypes = [{ name: "Hors d'oeuvres", id: 0 }, { name: "Soup", id: 1 }, { name: "Fish", id: 2 }, { name: "Salad", id: 3 }, { name: "Main course", id: 4 }, { name: "Dessert", id: 5 }];
var result = courseTypes.map(function (courseType) {
return {
    courseType: courseType.id,
    courseName: courseType.name,
    courses: selectedCourse.filter(function (course) {
        return course.courseType.includes(courseType.id);
    })
  };
}).filter(function (extended) {
   return extended.courses.length;
});

 console.log(JSON.stringify(result, null, 2));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM