简体   繁体   中英

JavaScript two arrays merge into new Array

I have two sets of arrays data, one for orders and one for picking orders. The order id of those arrays is the same. Data for picking orders is nested arrays. There is one value named orderHasAlcohol in the Picking orders data. I'd like to make a new array in which I can add orderHasAlcohol from the Orders data.

I am not sure how I can do it.

const ordersData = [
  {
    additionalInfo: null,
    comment: null,
    deliveryDate: "2022-07-14",
    deliveryMethod: "PICKUP",
    deliveryTime: "10-12",
    discountCode: null,
    id: "1234", // orderId
    orderStatus: "NEW",
    paymentMethod: "ON_DELIVERY",
    paymentStatus: "UNAVAILABLE",
    storeId: "12345",
  },
  {
    additionalInfo: null,
    comment: null,
    deliveryDate: "2022-07-23",
    deliveryMethod: "PICKUP",
    deliveryTime: "10-12",
    discountCode: null,
    id: "123", // orderId
    orderStatus: "NEW",
    paymentMethod: "ON_DELIVERY",
    paymentStatus: "UNAVAILABLE",
    storeId: "12345",
  },
  {
    additionalInfo: null,
    comment: null,
    deliveryDate: "2022-07-23",
    deliveryMethod: "PICKUP",
    deliveryTime: "10-12",
    discountCode: null,
    id: "198", // orderId
    orderStatus: "NEW",
    paymentMethod: "ON_DELIVERY",
    paymentStatus: "UNAVAILABLE",
    storeId: "12345",
  },

  {
    additionalInfo: null,
    comment: null,
    deliveryDate: "2022-07-23",
    deliveryMethod: "PICKUP",
    deliveryTime: "10-12",
    discountCode: null,
    id: "125", // orderId
    orderStatus: "NEW",
    paymentMethod: "ON_DELIVERY",
    paymentStatus: "UNAVAILABLE",
    storeId: "12345",
  },
];

const pickingOrder = {
  ordersPickedAndDone: {
    orderCount: 0,
    rows: [],
  },
  ordersPickedAndPaid: {
    orderCount: 0,
    rows: [],
  },
  ordersPickedCanStart: {
    orderCount: 2,
    rows: [
      {
        orderHasAlcohol: false,
        orderId: "123",
      },
      {
        orderHasAlcohol: true,
        orderId: "198",
      },
    ],
  },
  ordersPickingProgress: {
    orderCount: 2,
    rows: [
      {
        pickingRun: 1,
        partitions: [
          {
            orderHasAlcohol: false,
            orderId: "125",
          },
          {
            orderHasAlcohol: true,
            orderId: "1234",
          },
        ],
      },
    ],
  },
};

// This is my expected arrays output

const expectedArrays = [
  {
    additionalInfo: null,
    comment: null,
    deliveryDate: "2022-07-14",
    deliveryMethod: "PICKUP",
    deliveryTime: "10-12",
    discountCode: null,
    id: "1234", // orderId
    orderStatus: "NEW",
    paymentMethod: "ON_DELIVERY",
    paymentStatus: "UNAVAILABLE",
    storeId: "12345",
    orderHasAlcohol: true,
  },

  {
    additionalInfo: null,
    comment: null,
    deliveryDate: "2022-07-23",
    deliveryMethod: "PICKUP",
    deliveryTime: "10-12",
    discountCode: null,
    id: "123", // orderId
    orderStatus: "NEW",
    paymentMethod: "ON_DELIVERY",
    paymentStatus: "UNAVAILABLE",
    storeId: "12345",
    orderHasAlcohol: false,
  },
  {
    additionalInfo: null,
    comment: null,
    deliveryDate: "2022-07-23",
    deliveryMethod: "PICKUP",
    deliveryTime: "10-12",
    discountCode: null,
    id: "198", // orderId
    orderStatus: "NEW",
    paymentMethod: "ON_DELIVERY",
    paymentStatus: "UNAVAILABLE",
    storeId: "12345",
    orderHasAlcohol: true,
  },

  {
    additionalInfo: null,
    comment: null,
    deliveryDate: "2022-07-23",
    deliveryMethod: "PICKUP",
    deliveryTime: "10-12",
    discountCode: null,
    id: "125", // orderId
    orderStatus: "NEW",
    paymentMethod: "ON_DELIVERY",
    paymentStatus: "UNAVAILABLE",
    storeId: "12345",
    orderHasAlcohol: false,
  },
];

console.log({expectedArrays});

PS: I am using ramda for my function validation. it would be nice to create new array by using ramda. but not necessary.

I don't know Ramda but with native js it should looks like this :

First you simplify expectedArrays to get an array of object which associate the orderId to the property orderHasAlcohol :

let pickingOrderSimplified = Object.fromEntries(Object.keys(pickingOrder).map(key => {
    return  pickingOrder[key].rows.length > 0 && pickingOrder[key].rows.at(0).partitions ?  
            pickingOrder[key].rows.map(row => row.partitions).flat() : 
            pickingOrder[key].rows;
}).flat().map(el => [el.orderId, el.orderHasAlcohol]));

Then you can merge arrays :

let res = ordersData.map(data => ({
    ...data,
    orderHasAlcohol: pickingOrderSimplified[data.id]
}));

console.log(res);

I would suggest something like this:

let alcoholContentMap = {};
for (const key of Object.keys(pickingOrder)) {
  const orderCount = pickingOrder[key].orderCount;
  if (orderCount > 0) {
    for (const index = 0; index < orderCount; index++) {
      const currentOrder = pickingOrder[key].rows[index];

      if ('partitions' in currentOrder) {
        for (const partition of currentOrder)
          alcoholContentMap[partition.orderId] = partition.orderHasAlcohol;
      } else {
          alcoholContentMap[currentOrder.orderId] = partition.orderHasAlcohol;
      }
    }
  }
}
const expectedArrays = ordersData.map(order => {
  if (order.orderId in alcoholContentMap) {
    return {
      ...order,
      orderHasAlcohol: alcoholContentMap[order.orderId]
    }
  } else return order;
});

If you read this code, you'll see that the first part retrieves the information needed from pickingOrder and the second one applies it to your array. If it is in your hands, I would suggest simplifying the structure of the pickingOrder array in order to optimize the reading process, but anyways, this should work as well.

You could write a generator that yields the objects of interest from the picking order object.

I would also key the main data by id, so you can quickly find an object by id and merge more data into it.

 const ordersData = [{additionalInfo: null,comment: null,deliveryDate: "2022-07-14",deliveryMethod: "PICKUP",deliveryTime: "10-12",discountCode: null,id: "1234",orderStatus: "NEW",paymentMethod: "ON_DELIVERY",paymentStatus: "UNAVAILABLE",storeId: "12345",},{additionalInfo: null,comment: null,deliveryDate: "2022-07-23",deliveryMethod: "PICKUP",deliveryTime: "10-12",discountCode: null,id: "123",orderStatus: "NEW",paymentMethod: "ON_DELIVERY",paymentStatus: "UNAVAILABLE",storeId: "12345",},{additionalInfo: null,comment: null,deliveryDate: "2022-07-23",deliveryMethod: "PICKUP",deliveryTime: "10-12",discountCode: null,id: "198",orderStatus: "NEW",paymentMethod: "ON_DELIVERY",paymentStatus: "UNAVAILABLE",storeId: "12345",},{additionalInfo: null,comment: null,deliveryDate: "2022-07-23",deliveryMethod: "PICKUP",deliveryTime: "10-12",discountCode: null,id: "125",orderStatus: "NEW",paymentMethod: "ON_DELIVERY",paymentStatus: "UNAVAILABLE",storeId: "12345",},]; const pickingOrder = {ordersPickedAndDone: {orderCount: 0,rows: [],},ordersPickedAndPaid: {orderCount: 0,rows: [],},ordersPickedCanStart: {orderCount: 2,rows: [{orderHasAlcohol: false,orderId: "123",},{orderHasAlcohol: true,orderId: "198",},],},ordersPickingProgress: {orderCount: 2,rows: [{pickingRun: 1,partitions: [{orderHasAlcohol: false,orderId: "125",},{orderHasAlcohol: true,orderId: "1234",},],},],},}; // Yield objects from given data structure that have "orderId" property function* iterOrderInfo(obj) { if (Object(obj) !== obj) return; if (obj.orderId) yield obj; for (const value of Object.values(obj)) { yield* iterOrderInfo(value); } } // Key the main data by order id const map = new Map(ordersData.map(obj => [obj.id, {...obj}])); // Associate objects retrieved from picking order by id and merge them into the data for (const {orderId, ...rest} of iterOrderInfo(pickingOrder)) { Object.assign(map.get(orderId), rest); } // Retrieve the results const result = [...map.values()]; console.log(result);

Pragmatic solution

 const re = /"orderHasAlcohol":(true|false),"orderId":("\d+")/g; let alco = [...JSON.stringify(pickingOrder).matchAll(re)] .reduce((acc, entry) => { const key = entry[2].replaceAll('\"', ""); /// this could be more elegant acc[key] = entry[1] === "true"; return acc; }, {}); console.log(alco) ordersData.forEach(order => order.hasAlcohol = alco[order.id] ? ? false) console.log(ordersData)
 <script> const ordersData = [{ additionalInfo: null, comment: null, deliveryDate: "2022-07-14", deliveryMethod: "PICKUP", deliveryTime: "10-12", discountCode: null, id: "1234", // orderId orderStatus: "NEW", paymentMethod: "ON_DELIVERY", paymentStatus: "UNAVAILABLE", storeId: "12345", }, { additionalInfo: null, comment: null, deliveryDate: "2022-07-23", deliveryMethod: "PICKUP", deliveryTime: "10-12", discountCode: null, id: "123", // orderId orderStatus: "NEW", paymentMethod: "ON_DELIVERY", paymentStatus: "UNAVAILABLE", storeId: "12345", }, { additionalInfo: null, comment: null, deliveryDate: "2022-07-23", deliveryMethod: "PICKUP", deliveryTime: "10-12", discountCode: null, id: "198", // orderId orderStatus: "NEW", paymentMethod: "ON_DELIVERY", paymentStatus: "UNAVAILABLE", storeId: "12345", }, { additionalInfo: null, comment: null, deliveryDate: "2022-07-23", deliveryMethod: "PICKUP", deliveryTime: "10-12", discountCode: null, id: "125", // orderId orderStatus: "NEW", paymentMethod: "ON_DELIVERY", paymentStatus: "UNAVAILABLE", storeId: "12345", }, ]; const pickingOrder = { ordersPickedAndDone: { orderCount: 0, rows: [], }, ordersPickedAndPaid: { orderCount: 0, rows: [], }, ordersPickedCanStart: { orderCount: 2, rows: [{ orderHasAlcohol: false, orderId: "123", }, { orderHasAlcohol: true, orderId: "198", }, ], }, ordersPickingProgress: { orderCount: 2, rows: [{ pickingRun: 1, partitions: [{ orderHasAlcohol: false, orderId: "125", }, { orderHasAlcohol: true, orderId: "1234", }, ], }, ], }, }; </script>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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