Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Refactoring Javascript Function: Array transformation

I have a constant array like this:

const pie_values = [20,10,5,5,10];

The challenge is to transform the above array based on integer input.

(5) => [5, 15, 10, 5, 5, 10]
(21) => [20, 1, 9, 5, 5, 10]
(31) => [20, 10, 1, 4, 5, 10]

An input of 5 takes 5 from the first index of pie_values. But it still leaves 15.

An input of 21 can take 20 from index 0 and 1 from index 2, leaving 9

I think you can see how this is going. So (0) and (50) will return the original pie_values.

Now the challenge is to create a function that does this in a few lines of code, which is build on loops rather than on 5 if statements. In case pie_values is extended upon, the function should still work.

I have an approach working with if statements, however the latter is undoable. What would be a good approach to these kind of problems?

First I defined a helper function:

//Returns summation of pie value
// totalPieValues(1) = 20
// totalPieValues(2) = 30
// totalPieValues(3) = 35
// totalPieValues(4) = 40
// totalPieValues(5) = 50
function totalPieValues(max) {
  let result = 0;
  for (let i = 0; i < max; i++) {
    result += PIE_VALUES[i];
  }
  return result;
}

Then I worked on a function getPieArray which utilizes the helper function. This is where I am stuck

function getPieArray(wp) {
  for (let i = 0; i < PIE_VALUES.length; i++) {
    if (wp == 0 || wp == totalPieValues(i)) {
      return PIE_VALUES;
    }
  }

  let result = [];
  for (let i = 1; i <= PIE_VALUES.length; i++) {
    if (wp > totalPieValues(PIE_VALUES.length - i)) {
      result.push(PIE_VALUES[i]);
    } else if () {
      result.push(wp - totalPieValues(3));
    } else {
      result.push(PIE_VALUES[i] - (value - totalPieValues(3)));
    }
  }
  return result;
}

The code that I have written and works is here:

//Returns array of exact values needed to show in pie chart
export function getPieValues(wp) {
  //1 => [1, 19, 10, 5, 5, 10]
  //24 => [20, 4, 1, 5, 5, 10]
  //31 => [20, 10, 1, 5, 5, 5, 10]
  let result;
  if (wp == 0) {
    result = PIE_VALUES;
  } else if (wp < totalPieValues(1)) {
    result = [wp - totalPieValues(0), PIE_VALUES[0] - wp, PIE_VALUES[1], PIE_VALUES[2], PIE_VALUES[3], PIE_VALUES[4]];

  } else if (wp == totalPieValues(1)) {
    result = PIE_VALUES;
  } else if (wp < totalPieValues(2)) {
    result = [PIE_VALUES[0], wp - totalPieValues(1), PIE_VALUES[1] - (wp - PIE_VALUES[0]), PIE_VALUES[2], PIE_VALUES[3], PIE_VALUES[4]];

  } else if (wp == totalPieValues(2)) {
    result = PIE_VALUES;
  } else if (wp < totalPieValues(3)) {

    result = [PIE_VALUES[0], PIE_VALUES[1], wp - totalPieValues(2), PIE_VALUES[2] - (wp - totalPieValues(2)), PIE_VALUES[3], PIE_VALUES[4]];

  } else if (wp == totalPieValues(3)) {
    result = PIE_VALUES;

  } else if (wp < totalPieValues(4)) {

    result = [PIE_VALUES[0], PIE_VALUES[1], PIE_VALUES[2], wp - totalPieValues(3), PIE_VALUES[3] - (wp - totalPieValues(3)), PIE_VALUES[4]];

  } else if (wp == totalPieValues(4)) {
    result = PIE_VALUES;

  } else if (wp < totalPieValues(5)) {

    result = [PIE_VALUES[0], PIE_VALUES[1], PIE_VALUES[2], PIE_VALUES[3], wp - totalPieValues(4), PIE_VALUES[4] - (wp - totalPieValues(4))];

  } else if (wp == totalPieValues(5)) {
    result = PIE_VALUES;
  }

  return result;
}
like image 766
Fullhdpixel Avatar asked Feb 16 '26 21:02

Fullhdpixel


1 Answers

This is super overkill

You can just iterate through the array and "eat" the index value and continue

function pieArray(inputArray, value){
   let copyOfValue = value;
   return inputArray.reduce((sum, input, index) => { // <-- index here
     copyOfValue -= input;
     if(copyOfValue > 0){
        sum.push(input);
     }else{
        sum.push(input+copyOfValue);
        sum.push(Math.abs(copyOfValue));
        copyOfValue = Number.MAX_VALUE; //Hacky solution, just change value to max value
     }
     return sum;
   }, []);
}

Tests

pieArray([20,10,5,5,10], 5) => [5, 15, 10, 5, 5, 10]

pieArray([20,10,5,5,10], 21) => [20, 1, 9, 5, 5, 10]

pieArray([20,10,5,5,10], 31) => [20, 10, 1, 4, 5, 10]

like image 146
Pavlo Avatar answered Feb 18 '26 11:02

Pavlo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!