首页 > 解决方案 > 将包含空数组的对象数组映射为属性会忽略整个对象

问题描述

我有一个对象数组-

let initialArr = [
  {
    "id": 1,
    "name": "product name",
    "product_details": [
      {
        "id": 1,
        "details": "some details"
      }
    ],
    "subscriptions": [
      {
        "id": 1,
        "subs": "7 days"
      },
      {
        "id": 2,
        "subs": "15 days"
      }
    ]
  },
  {
    "id": 2,
    "name": "product name 2",
    "product_details": [
      {
        "id": 2,
        "details": "some details 2"
      }
    ],
    "subscriptions": [
      {
        "id": 1,
        "subs": "7 days"
      },
      {
        "id": 2,
        "subs": "15 days"
      }
    ]
  },
  {
    "id": 3,
    "name": "product name 3",
    "product_details": [
      {
        "id": 3,
        "details": "some details 3"
      }
    ],
    "subscriptions": []
  }
]

这就是我想要实现的 -

[
  {
    "id": 1,
    "name": "product name",
    "detailsId" : 1,
    "details": "some details"
    "subsId": 1,
    "subs": "7 days"
  },
  {
    "id": 1,
    "name": "product name",
    "detailsId" : 1,
    "details": "some details"
    "subsId": 2,
    "subs": "15 days"
  },
  {
    "id": 2,
    "name": "product name 2",
    "detailsId" : 2,
    "details": "some details 2"
    "subsId": 1,
    "subs": "7 days"
  },
  {
    "id": 2,
    "name": "product name 2",
    "detailsId" : 2,
    "details": "some details 2"
    "subsId": 2,
    "subs": "15 days"
  },
  {
    "id": 3,
    "name": "product name 3",
    "detailsId" : 3,
    "details": "some details 3"
  }
]

这就是我所做的 -

initialArr.map(e => {
  e.product_details.map(p =>{
   e.subscriptions.map(s => {
      newArr.push({
        id: e.id,
        name: e.name,
        detailsId: p.id,
        details: p.details,
        subsId: s.id,
        subs:s.subs        
      }); 
   }); 
  })
})

如果订阅数组不为空,则此方法有效。如果对于某些产品,订阅数组为空,则该产品不会被推送到数组中。在我无法弄清楚如何解决它。

第三个产品未推送到新阵列中。这就是我得到的 -

[
  {
    "id": 1,
    "name": "product name",
    "detailsId" : 1,
    "details": "some details"
    "subsId": 1,
    "subs": "7 days"
  },
  {
    "id": 1,
    "name": "product name",
    "detailsId" : 1,
    "details": "some details"
    "subsId": 2,
    "subs": "15 days"
  },
  {
    "id": 2,
    "name": "product name 2",
    "detailsId" : 2,
    "details": "some details 2"
    "subsId": 1,
    "subs": "7 days"
  },
  {
    "id": 2,
    "name": "product name 2",
    "detailsId" : 2,
    "details": "some details 2"
    "subsId": 2,
    "subs": "15 days"
  }
]

注意:虽然相同的产品在新数组中重复了两次,但这是要求 - 产品根据订阅数组的“subs”属性。

假设除了“订阅”之外我还有更多数组,例如“自定义”、“订单”等,并且我希望这些数组的数据也被推送,这是对多个数组执行的正确方法吗?

标签: javascriptarraysjsonobject

解决方案


假设数组 product_details 总是有 1 个元素及其数据,这是一个解决方案。
使用Array#reduce来累积新的结果数组。使用所有数据创建 foreach 元素一个新的临时对象。如果订阅数组为空,则将此临时对象推送到您的累积结果数组。否则,使用Array#forEach迭代您的订阅。对于每个订阅,使用Object.assign来制作临时对象的副本。添加订阅数据并将其推送到结果数组。

const initialArr = [{ id: 1, name: "product name", product_details: [{ id: 1, details: "some details" }], subscriptions: [{ id: 1, subs: "7 days" }, { id: 2, subs: "15 days" }] }, { id: 2, name: "product name 2", product_details: [{ id: 2, details: "some details 2" }], subscriptions: [{ id: 1, subs: "7 days" }, { id: 2, subs: "15 days" }] }, { id: 3, name: "product name 3", product_details: [{ id: 3, details: "some details 3" }], subscriptions: [] }];

let res = initialArr.reduce((acc, cur) => {
    let temp = {
        id: cur.id,
        name: cur.name,
        detailsId: cur.product_details[0].id,
        details: cur.product_details[0].details
    }
    if (!cur.subscriptions.length)
        acc.push(temp);
    else {
        cur.subscriptions.forEach(subs => {
            let tempSub = Object.assign({}, temp);
            tempSub.subsId = subs.id;
            tempSub.subs = subs.subs;
            acc.push(tempSub);
        })
    }
    return acc;
}, []);

console.log(res);

这里有一个没有reduceand的版本forEach

const initialArr = [{ id: 1, name: "product name", product_details: [{ id: 1, details: "some details" }], subscriptions: [{ id: 1, subs: "7 days" }, { id: 2, subs: "15 days" }] }, { id: 2, name: "product name 2", product_details: [{ id: 2, details: "some details 2" }], subscriptions: [{ id: 1, subs: "7 days" }, { id: 2, subs: "15 days" }] }, { id: 3, name: "product name 3", product_details: [{ id: 3, details: "some details 3" }], subscriptions: [] }];

let acc = [];
initialArr.forEach(cur => {
    let temp = {
        id: cur.id,
        name: cur.name,
        detailsId: cur.product_details[0].id,
        details: cur.product_details[0].details
    }
    if (!cur.subscriptions.length)
        acc.push(temp);
    else {
        cur.subscriptions.forEach(subs => {
            let tempSub = Object.assign({}, temp);
            tempSub.subsId = subs.id;
            tempSub.subs = subs.subs;
            acc.push(tempSub);
        })
    }
});

console.log(acc);


推荐阅读