freeCodeCamp Challenge Guide: Inventory Update

Messy code using reduce

function updateInventory(arr1, arr2) {

//Draw final object
var result = arr1.reduce(function(acumulator, element){
	if(acumulator[element[1]] === undefined){
		acumulator[element[1]] = element[0];
	} else {
		acumulator[element[1]] += element[0];
	}
	return acumulator;
}, {});
arr2.reduce(function(acumulator, element){
		if(result[element[1]] === undefined){
			result[element[1]] = element[0];
		} else {
			result[element[1]] += element[0];
		}

		return acumulator;
	}, {});

var resultArray = [];
var resultKeys = Object.keys(result).sort();
for(var i = 0; i < resultKeys.length; i ++){
	resultArray.push([result[resultKeys[i]], resultKeys[i]]);
}
//console.log(resultArray);

// All inventory must be accounted for or you're fired!
return resultArray;

}

Can’t get my head around using reduce and map functions… but this was surprisingly easy to achieve using an object, and a simple for loop.

function updateInventory(arr1, arr2) {
  // holds the concatenation of arr1 and arr2
  var concat = [];
  // an object which will help getting rid of duplicates
  var obj = {};
  // the final output array
  var out = [];

  concat = arr1.concat(arr2);

  // Simple loop to either add a key to the obj object
  // OR increment the value of the existing key.
  for (var i = 0, len = concat.length; i < len; i++){
    if (obj[concat[i][1]])
      obj[concat[i][1]] += concat[i][0];
    else
      obj[concat[i][1]] = concat[i][0];
  }
  // converting back the object to an array
  // basically looping through the keys, adding an array
  // in the form of [value, "Key"]
  for (i in obj){
   out.push([obj[i], i]); 
  }

  // Sorting the array by comparing the "Key"
  out.sort(function(a, b){
    return (a[1] > b[1]);
  });

  return out;
}
1 Like

After the last challenge, this one wa very easy!! Hey @Rafase282 @camperbot , do you Gus believe it could fit as a clean solution? It looks pretty small!.. Let me know your opinion:

function updateInventory(arr1, arr2) {
    // All inventory must be accounted for or you're fired!
 
  // create a Map object and push inventory to it
  const inventoryMap = new Map();
  
  for (const el of arr1) {
    inventoryMap.set(el[1], el[0]);
  }
  
  // add elements to the Map object, check wich ones are already there, and sum it
  for (const el of arr2) {
    let quantity = el[0];
    if (inventoryMap.has(el[1])) {
      quantity += inventoryMap.get(el[1]);
    }
    inventoryMap.set(el[1], quantity);
  }
  
  // spread Map object to an array again
  const updatedInventory = [...inventoryMap];
  
  // invert key/value position
  updatedInventory.forEach((el) => el.reverse());
  
  //sort it aplhabetically
  updatedInventory.sort((a, b) => a[1].charCodeAt(0) - b[1].charCodeAt(0));
  
  return updatedInventory;
}

function updateInventory(arr1, arr2) {
    // All inventory must be accounted for or you're fired!
  var objArr1 = arr1.reduce(function (a, b){ a[b[1]] = b[0]; return a;},{});
  var objArr2 = arr2.reduce(function (a, b){ a[b[1]] = b[0]; return a;},{});
  
  
 for (var v in objArr2){
   if(objArr1.hasOwnProperty(v)){
     objArr1[v] += objArr2[v]; 
   } else{
     objArr1[v] = objArr2[v];
   }
 }
  
  var fArray = Object.keys(objArr1).map(function (x){return [objArr1[x], x]; });
  
  fArray.sort(comp);
  
  function comp(a, b) {
    if (a[1] === b[1]) {
        return 0;
    }
    else {
        return (a[1] < b[1]) ? -1 : 1;
    }
}
  
  return fArray;
}

My answer with the arrays concatenated, one for loop and no sort, so it’s done in one pass through. Not sure if this is more efficient by virtue of doing it in one loop and not using sort, but it was a tough challenge to get to work so I’m happy with it. Let me know what you think:

function updateInventory(arr1, arr2) {
  var exists = {};
  
 var arrAll = arr1.concat(arr2);
 
 for (x = 0; x < arrAll.length; x++) {
     var y = x;
     if (exists[arrAll[y][1]] !== undefined) {
       arrAll[exists[arrAll[y][1]]][0] += arrAll[y][0];
       arrAll.splice(y,1);
       y--;
      }
     while (y > 0 && arrAll[y][1] < arrAll[y - 1][1]) {
       arrAll.splice(y-1,0,arrAll[y]);
       arrAll.splice(y+1,1);
       exists[arrAll[y][1]] = y;
       y--;
     }
     exists[arrAll[y][1]] = y;
 }
 return arrAll;
}

This is possibly a cleaner solution. I’d like to know what you think. Here’s what I’m doing: Reverse the inner arrays and convert to map, then update the inventories and convert back to a 2D array in the original format.


function updateInventory(arr1, arr2) {
   let currInvMap = new Map(arr1.map( (el) => el.reverse() ));
   let newInvMap = new Map(arr2.map( (el) => el.reverse() ));
   for( let [product, value] of newInvMap ){
       if(currInvMap.has(product)){
       	 currInvMap.set(product, currInvMap.get(product) + value );
       }
       else{
         currInvMap.set(product, value)
       }
   }
   return [...currInvMap].sort().map( (el) => el.reverse() );
}

1 Like