将包含空数组的对象映射为属性会忽略整个对象

时间:2020-08-30 14:07:38

标签: javascript arrays json object

我有一个对象数组-

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

如果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"
  }
]

注意:尽管同一产品在新阵列中重复两次,但这是必需的-根据订阅阵列的“ subs”属性的产品。

假设我有更多的数组例如除了“订阅”之外,还有“定制”,“订单”等,而且我还希望推送这些数组的数据,这是对多个数组进行处理的正确方法吗?

3 个答案:

答案 0 :(得分:2)

假设数组product_details始终具有1个元素,这是一种解决方案。
使用Array#reduce累积新的结果数组。用所有数据创建一个新的临时对象foreach元素。如果subscriptions数组为空,则将此临时对象推送到您的累积结果数组。否则,请使用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);

这里没有reduce,而是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);

答案 1 :(得分:1)

您可以检查subscription的长度并返回一个对象而不是映射数组。

const
    data = [{ 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: [] }],
    result = data.flatMap(({ product_details: [{ id: detailsId, details }], subscriptions, ...o }) => subscriptions.length
        ? subscriptions.map(({ id: subsId, subs }) => ({ ...o, detailsId, details, subsId, subs }))
        : ({ ...o, detailsId, details })
    );

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 2 :(得分:0)

您需要明确处理此案:

if (e.subscriptions.length === 0) {
  newArr.push({ ... }
} else {
  e.subscriptions.map(...)
}

您还应该使用forEach而不是map