Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making a conditional function more efficient

I want to make a function that modifies a variable based on the given argument.

The function checks a variable and the number in that string. Then via the argument, I specify either increase or decrease the number by 1 (++1).

There is an array as well, that if the number is equal to the length of the array, then it turns to 1 and if the number is less than 1 then it is equal the size of the array. This is to make sure the number of the string does not get less than 1 or more than the length of the array.

the string with the number is Music1. So the circle would be like: ...., Music1, Music2, Music3, Music4, Music1, Music2, Music3, ....

var MyArray = ["Music1", "Music2", "Music3", "Music4"];
var currentMusic = "Music1";

$(".increase").on('click tap', nextMusic);
$(".decrease").on('click tap', previousMusic);

function nextMusic() {
  unaryChange('plus')
}

function previousMusic() {
  unaryChange('minus')
}

function unaryChange(operation) {
  if (currentMusic === "Music4") {
    currentMusic = "Music1"
  } else if (currentMusic === "Music0") {
    currentMusic = "Music4"
  }
  if (operation === "plus") {
    currentMusic = currentMusic.replace(/\d+$/, function(n) {
      return ++n
    });
  } else {
    currentMusic = currentMusic.replace(/\d+$/, function(n) {
      return --n
    });
  }

  console.log(currentMusic);
  $(".text").text(currentMusic);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<button class="increase">increase</button>
<button class="decrease">decrease</button>
<p class="text">value</p>

The above method almost does the job, however I am looking for an easier and more professional solution. It does not look efficient. For example, there must be a better way to specify the argument operation instead of a string like plus, or the conditions.

I need this function to be rewritten in a better way, more professionally and works as described.

Thanks in advance.

like image 419
Danny Avatar asked Dec 14 '22 11:12

Danny


2 Answers

It is better to work with array index instead of the values

function unaryChange(operation) {
  var currentIndex = MyArray.findIndex(function(item) {
    return item === currentMusic;
  });

  if(operation === 'plus') {
    newIndex = currentIndex < MyArray.length - 1 && currentIndex + 1 || 0;
  } else {
    newIndex = currentIndex > 0 ? currentIndex -1 : MyArray.length -1;
  }

  currentMusic = MyArray[newIndex]
  $(".text").text(currentMusic);
}

In this case whatever the size of the array it will work.

A working example https://jsbin.com/rahomorupa/4/edit?html,js,console,output

like image 198
Joe Hany Avatar answered Dec 17 '22 23:12

Joe Hany


Building on Joe's answer I'd suggest you define constants for plus and minus as +1 and -1 respectively to simplify the increment/decrement logic, along with the modulus operator to handle the array wrap-around:

const PLUS = 1;
const MINUS = -1;

function unaryChange(operation) {
  var currentIndex = MyArray.findIndex(function(item) {
    return item === currentMusic;
  });

  // If it's invoked as unaryChange(PLUS) or unaryChange(MINUS)
  // we don't need any conditional logic to handle the increment,
  // and with the % operator we don't need additional bounds overflow
  // logic. (This latter bit is complicated somewhat by the need to
  // handle a minus step from index 0.)
  const {length} = MyArray;
  const newIndex = ((currentIndex + operation) % length + length) % length;

  currentMusic = MyArray[newIndex]
  $(".text").text(currentMusic);
}

The % operator returns the remainder of a division, which conveniently loops back around to 0 when used with an array index against the array length:

const array = ['first', 'second', 'third'];

for (let i = 0; i < 20; i++) {
  console.log(array[i % array.length]);
}
like image 30
ray hatfield Avatar answered Dec 17 '22 22:12

ray hatfield