Home > other >  JavaScript two arrays merge into new Array
JavaScript two arrays merge into new Array

Time:07-13

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

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

CodePudding user response:

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.

CodePudding user response:

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

CodePudding user response:

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

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

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

console.log(res);
  • Related