Imagine you are a company that wants to assist some US-based companies  to ship their goods to customers in Hamburg. To achieve this, lets  assume that every order can be represented by a tuple (orderId,  companyName, customerAddress, orderedItem).Thus, some sample data might look like this:001, SuperTrader, Steindamm 80, Macbook002, Cheapskates, Reeperbahn 153, Macbook003, MegaCorp, Steindamm 80, Book Guide to Hamburg004, SuperTrader, Sternstrasse 125, Book Cooking 101005, SuperTrader, Ottenser Hauptstrasse 24, Inline Skates006, MegaCorp, Reeperbahn 153, Playstation007, Cheapskates, Lagerstrasse 11, Flux compensator008, SuperTrader, Reeperbahn 153, Inline SkatesInstructions:Using node.js, please implement a working solution to perform the following kind of operations on the data:show all orders from a particular companyshow all orders to a particular addressdelete a particular order given an OrderIddisplay how often each item has been ordered, in descending order (ie in the above example, 2x for Macbook and Inline skates, 1x for the rest)Note:Please optimize your code and do not convolute it with handling  exceptions/edge cases  we are more interested in readability for this  solution.Solution:const data = [  // orderId, company, custAddr, product  ['001', 'SuperTrader', 'Steindamm 80', 'Macbook'],  ['002', 'Cheapskates', 'Reeperbahn 153', 'Macbook'],  ['003', 'MegaCorp', 'Steindamm 80, Book', 'Guide to Hamburg'],  ['004', 'SuperTrader', 'Sternstrasse 125', 'Book Cooking 101'],  ['005', 'SuperTrader', 'Ottenser Hauptstrasse 24', 'Inline Skates'],  ['006', 'MegaCorp', 'Reeperbahn 153', 'Playstation'],  ['007', 'Cheapskates', 'Lagerstrasse 11', 'Flux compensator'],  ['008', 'SuperTrader', 'Reeperbahn 153', 'Inline Skates'],];// show all orders from a particular companyconst allCompanyOrders = (orders, company) => { // O(n)  return orders.filter((o) => o[1] === company);};// all orders to an addressconst allOrdersToAddress = (orders, address) => { //O(n)  return orders.filter((o) => o[2] === address);};// delete an orderconst removeOrder = (orders, id) => { // O(n)  const result = [];  orders.forEach((o) => {    if (o[0] !== id) {      result.push(o);    }  });  return result;};const itemsCount = (orders) => {  const map = Object.create(null);  orders.forEach((o) => {    const name = o[3];    const count = map[name] || 0;    map[name] = count + 1;  });  return map;};//show often ordered items in descending orderedconst showMostFrequent = (orders) => {  const map = itemsCount(orders);   const result = [];  const keys = Object.keys(map);  for (let name of keys) {    const count = map[name];    result.push({name, count});  }  // O(nlogn) + O(n) memory  return result.sort((a, b) => b.count - a.count)    .map((o) => o.name);};console.log(allCompanyOrders(data, 'SuperTrader').length === 4);console.log(allOrdersToAddress(data, 'Reeperbahn 153').length === 3);console.log(removeOrder(data, '007').length === 7);console.log(showMostFrequent(data));Questions:Should I preprocess data for optimisation at cost of memory?Right now I have to use indexes everywhere which feels uncomfortable.
Shipping company investigation
javascript;performance;node.js;interview questions
I'd definitely map the tuples to objects, to avoid all the index stuff later on. In this case, the question specifically says it's all about readability, so don't worry about memory usage (also because it's next to nothing).const orders = data.map(order => {  const [orderId, companyName, companyAddress, orderedItem] = order;  return { orderId, companyName, companyAddress, orderedItem };});As for the rest of the code:Your removeOrder could be implemented using filter, just like the all* functions; no need to manually push to a new array. And your showMostFrequent and itemsCount functions could both be implemented using map - again instead of manually pushing to a new array/object.Overall though, I'd wrap everything in an Orders object/class, instead of passing the orders array on every call. Maybe something like this:class Orders {  constructor(data) {    this.orders = data.map(order => {      const [orderId, companyName, companyAddress, orderedItem] = order;      return { orderId, companyName, companyAddress, orderedItem };    });  }  // note: Assumes orderIds are unique  remove(orderId) {    const index = this.orders.findIndex(order => order.orderId === orderId);    if (index === -1) {      return null;    } else {      const order = this.orders[index];      this.orders.splice(index, 1);      return order;    }  }  findBy(property, value) {    return this.orders.filter(order => order[property] === value);  }  findByCompanyName(name) {    return this.findBy('companyName', name);  }  findByCompanyAddress(address) {    this.findBy('companyAddress', address);  }  itemCounts() {    const grouped = this.orders.reduce((memo, order) => {      memo[order.orderedItem] = memo[order.orderedItem] || 0;      memo[order.orderedItem] += 1;      return memo;    }, {})    return Object      .keys(grouped)      .map(key => { return { orderedItem: key, count: grouped[key] } })      .sort((a, b) => a.count - b.count)      .reverse();  }};I've added a generic findBy method that's used by other two findBy* methods. But more importantly, the remove method now modifies the list of orders, and returns the removed order object (or null), rather than return a new array.