【问题标题】:javascript - merge, combine, transform 2 different arrays of Objectsjavascript - 合并、组合、转换 2 个不同的对象数组
【发布时间】:2019-03-13 01:02:17
【问题描述】:

我不知道如何转换和组合 2 个对象数组。

我有这 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}
]

第一个 JSON 中的 courseType 属性是一个数字数组,对应于第二个 JSON 中的 courseTypes 索引和属性 id

这个案例的结果应该是这样的:

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",
      }
    ]
  }
]

预期结果必须通过 courseType 属性过滤来组合 2 个数组。

【问题讨论】:

  • 在“result”内的第二个对象上,“courseType”属性等于 2
  • 当我阅读第一段时,我想“太好了!终于有人不调用 JavaScript 对象 JSON”了。太糟糕了,它进入了第二段......
  • 你的预期输出有 courseType: 3, courseName: "Fish" 我想这是一个错字,因为 Fish 在你的输入中有一个 id 2?

标签: javascript arrays javascript-objects


【解决方案1】:

您可以像这样使用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));

说明:

courseTypes.map 遍历您的第二个输入数组,并针对它在selectedCourse 中找到的每种类型,哪些课程与该特定类型匹配。

它使用.filter 来收集这些匹配项。 filter 回调使用 includes 来确定是否匹配——它返回一个布尔值,正是过滤器回调期望的返回值。

然后将此过滤后的数组添加到对象字面量中,该对象字面量还定义了其他两个属性courseTypecourseName。该新对象是课程类型映射到的对象。 courseTypes.map 返回这些对象的数组。

最后,该结果可能包含具有空 courses 数组的条目。再次调用.filter 会过滤掉这些内容。如果该courses 数组的length 不为零,则保留该对象,否则将其踢出结果。

对于旧版浏览器

这是与旧版浏览器兼容的相同代码(没有箭头函数,没有 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));

【讨论】:

  • 很好的解决方案,但我只需要在结果中显示包含课程的 courseTypes,因此如果长度为 0,则不应显示。正如您在我的示例中看到的那样:)
  • 您在发表评论之前看到我发布的更新了吗?我还添加了一个解释。
【解决方案2】:

假设您想要所有带有selectedCourse 的项目,您可以使用Map 并收集所有课程,然后从找到的值中创建一个新数组。

这个解决方案也包括

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

【讨论】:

  • 一如既往的好答案:)
【解决方案3】:

虽然“trincot”代码适用于 chrome 和 Mozila,但它不适用于 IE edge 和 IE 10 及以下版本,您需要将其转换为纯 JavaScript。以下是适用于所有浏览器的代码。

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

【讨论】:

  • “以上代码”是什么意思?请注意,答案是按用户设置排序的,因此说“高于”没有多大意义。最好以评论的形式在答案本身下制作此类 cmets ;-)
  • 您似乎暗示 Edge 不支持 includes,但确实如此。注意:“IE 边缘”不是一个东西。它是 IE 或 Edge。
猜你喜欢
  • 2011-11-01
  • 1970-01-01
  • 2018-11-24
  • 2021-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-22
相关资源
最近更新 更多