Ajay K
Ajay K

Reputation: 85

Javascript group data and append additional data

I am looking to solve 2 problems here

  1. Group the orders to create an items array based on based on orderNo
  2. Include the tracking-information from the tracking array in tracking.json into the orders array.

So far I have only managed to get started with the grouping.

//orders.json
    const orders = [
      {
             "orderNo": "1",
             "tracking_number": "001",
             "courier": "FedEx",
             "street": "1745 T Street Southeast",
             "zip_code": 20020,
             "city": "Louisville",
             "destination_country": "USA",
             "email": "[email protected]",
             "articleNo": "A",
             "articleImageUrl": "watch.jpg",
             "quantity": 1,
             "product_name": "Watch"
            },
            {
             "orderNo": "1",
             "tracking_number": "001",
             "courier": "FedEx",
             "street": "1745 T Street Southeast",
             "zip_code": 20020,
             "city": "Louisville",
             "destination_country": "USA",
             "email": "[email protected]",
             "articleNo": "B",
             "articleImageUrl": "belt.jpg",
             "quantity": 2,
             "product_name": "Belt"
            },
            {
             "orderNo": "2",
             "tracking_number": "002",
             "courier": "FedEx",
             "street": "637 Britannia Drive",
             "zip_code": 94591,
             "city": "Vallejo",
             "destination_country": "USA",
             "email": "[email protected]",
             "articleNo": "",
             "articleImageUrl": "",
             "quantity": "",
             "product_name": ""
            }
    ];

//tracking.json
const tracking = [{
         "tracking_number": "001",
         "location": "",
         "timestamp": "2018-04-01T00:00:00.000Z",
         "status": "OrderProcessed",
         "status_text": "Order processed",
         "status_details": "The order has been processed."
        },
        {
         "tracking_number": "002",
         "location": "",
         "timestamp": "2018-04-06T05:58:00.000Z",
         "status": "OrderProcessed",
         "status_text": "Order processed",
         "status_details": "The order has been processed."
        }  
]

//expected output data.json
   const data = [
      {
         "orderNo":"1",
         "tracking_number":"001",
         "courier":"FedEx",
         "street":"1745 T Street Southeast",
         "zip_code":"20020",
         "city":"Louisville",
         "destination_country":"USA",
         "email":"[email protected]",
         "articleNo":"A",
         "articleImageUrl":"watch.jpg",
         "quantity":"1",
         "product_name":"Watch",
         "items":[
            {
               "articleNo":"A",
               "articleImageUrl":"watch.jpg",
               "quantity":"1",
               "product_name":"Watch"
            },
            {
               "articleNo":"B",
               "articleImageUrl":"belt.jpg",
               "quantity":"2",
               "product_name":"Belt"
            }
         ],
         "tracking":{
            "tracking_number":"001",
            "location":null,
            "timestamp":"2018-04-01T00:00:00.000Z",
            "status":"Scheduled",
            "status_text":"Order processed",
            "status_details":"The order has been processed."
         }
      },
      {
         "orderNo": "2",
         "tracking_number": "002",
         "courier": "FedEx",
         "street": "637 Britannia Drive",
         "zip_code": 94591,
         "city": "Vallejo",
         "destination_country": "USA",
         "email": "[email protected]",
         "articleNo": "",
         "articleImageUrl": "",
         "quantity": "",
         "product_name": "",
         "items":[
            
         ],
         "tracking":{
            "tracking_number": "002",
            "location": "",
            "timestamp": "2018-04-06T05:58:00.000Z",
            "status": "OrderProcessed",
            "status_text": "Order processed",
            "status_details": "The order has been processed."
         }
      }
   ]

const groupBy = key => array =>
      array.reduce(
        (objectsByKeyValue, obj) => ({
          ...objectsByKeyValue,
          [obj[key]]: (objectsByKeyValue[obj[key]] || []).concat(obj)
        }),
        {}
      );

const groupByOrders = groupBy('orderNo');

I am looking to get the data in the format shown in data.json

This is the current code along with the data

Code

Upvotes: 0

Views: 96

Answers (2)

Nina Scholz
Nina Scholz

Reputation: 386730

You could take two objects as reference to same orderNo and tracking_number.

For adding an oder to the result set remove item properties and take a new object of this properties.

const
    orders = [{ orderNo: "1", tracking_number: "001", courier: "FedEx", street: "1745 T Street Southeast", zip_code: 20020, city: "Louisville", destination_country: "USA", email: "[email protected]", articleNo: "A", articleImageUrl: "watch.jpg", quantity: 1, product_name: "Watch" }, { orderNo: "1", tracking_number: "001", courier: "FedEx", street: "1745 T Street Southeast", zip_code: 20020, city: "Louisville", destination_country: "USA", email: "[email protected]", articleNo: "B", articleImageUrl: "belt.jpg", quantity: 2, product_name: "Belt" }, { orderNo: "2", tracking_number: "002", courier: "FedEx", street: "637 Britannia Drive", zip_code: 94591, city: "Vallejo", destination_country: "USA", email: "[email protected]", articleNo: "", articleImageUrl: "", quantity: "", product_name: "" }],
    tracking = [{ tracking_number: "001", location: "", timestamp: "2018-04-01T00:00:00.000Z", status: "OrderProcessed", status_text: "Order processed", status_details: "The order has been processed." }, { tracking_number: "002", location: "", timestamp: "2018-04-06T05:58:00.000Z", status: "OrderProcessed", status_text: "Order processed", status_details: "The order has been processed." }],
    keys = ["articleNo", "articleImageUrl", "quantity", "product_name"],
    items = {},
    trackings = {},
    result = [];

for (let order of orders) {
    const item = {};
    for (const key of keys) {
        let value;
        ({ [key]: value, ...order } = order);
        item[key] = value;
    }
    if (!items[order.orderNo]) result.push(items[order.orderNo] = { ...order, items: [] });
    if (Object.values(item).some(Boolean)) items[order.orderNo].items.push(item);
    trackings[order.tracking_number] = items[order.orderNo];
}
for (const transfer of tracking) trackings[transfer.tracking_number].tracking = transfer;

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

Upvotes: 2

jsN00b
jsN00b

Reputation: 3691

Below is one possible way to achieve the target.

Code Snippet

const groupAndInclude = (base, delta) => {
  const result = [];        // result array
  base.forEach(             // iterate over the "orders"
    ({                      // de-structure to directly access specific props
      orderNo, tracking_number, articleNo,
      articleImageUrl, quantity, product_name,
      ...rest               // remaining props not directly-accessed
    }) => {
      const foundOrder = result.find(     // find if "order" already in "result"
        ob => ob.orderNo === orderNo
      );
      if (foundOrder) {                   // found a match, simply push "article"-info
        if (articleNo.length > 0) {       // push to "items" only if not "empty"
          foundOrder.items.push({         // to the "items" array
            articleNo, articleImageUrl, quantity, product_name
          })
        }
      } else {                            // match not-found. Add new entry to "result"
        const resObj = {                  // construct the result-object "resObj"
          ...rest, orderNo                // using all relevant "order" props
        };
        if (articleNo.length > 0) {       // do not add "empty" item
          resObj.items = [{               // add "items" as an array
            articleNo, articleImageUrl, quantity, product_name
          }];
        } else {
          resObj.items = [];
        };
        const foundTracker = delta.find(    // look for "tracking_number"
          ob => ob.tracking_number === tracking_number
        );
        // if "tracking_number" found, add to result-object
        if (foundTracker) resObj.tracking = {...foundTracker};
        result.push(resObj);              // push the result-object to the "result" array
      }
    }
  );
  return result;                          // explicitly return the "result" array
};
const orders = [{
    "orderNo": "1",
    "tracking_number": "001",
    "courier": "FedEx",
    "street": "1745 T Street Southeast",
    "zip_code": 20020,
    "city": "Louisville",
    "destination_country": "USA",
    "email": "[email protected]",
    "articleNo": "A",
    "articleImageUrl": "watch.jpg",
    "quantity": 1,
    "product_name": "Watch"
  },
  {
    "orderNo": "1",
    "tracking_number": "001",
    "courier": "FedEx",
    "street": "1745 T Street Southeast",
    "zip_code": 20020,
    "city": "Louisville",
    "destination_country": "USA",
    "email": "[email protected]",
    "articleNo": "B",
    "articleImageUrl": "belt.jpg",
    "quantity": 2,
    "product_name": "Belt"
  },
  {
    "orderNo": "2",
    "tracking_number": "002",
    "courier": "FedEx",
    "street": "637 Britannia Drive",
    "zip_code": 94591,
    "city": "Vallejo",
    "destination_country": "USA",
    "email": "[email protected]",
    "articleNo": "",
    "articleImageUrl": "",
    "quantity": "",
    "product_name": ""
  }
];
//tracking.json
const tracking = [{
    "tracking_number": "001",
    "location": "",
    "timestamp": "2018-04-01T00:00:00.000Z",
    "status": "OrderProcessed",
    "status_text": "Order processed",
    "status_details": "The order has been processed."
  },
  {
    "tracking_number": "002",
    "location": "",
    "timestamp": "2018-04-06T05:58:00.000Z",
    "status": "OrderProcessed",
    "status_text": "Order processed",
    "status_details": "The order has been processed."
  }
];

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

Explanation

Inline comments added in the snippet above.

Upvotes: 2

Related Questions