简体   繁体   English

使条件函数更有效

[英]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). 然后通过参数,我指定将数字增加或减少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. 还有一个数组,如果数字等于数组的长度,则它变为1,如果数字小于1,则它等于数组的大小。 This is to make sure the number of the string does not get less than 1 or more than the length of the array. 这是为了确保字符串的数量不会小于1或大于数组的长度。

the string with the number is Music1 . 数字的字符串是Music1 So the circle would be like: ...., Music1, Music2, Music3, Music4, Music1, Music2, Music3, .... 所以圈子就像: ...., 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. 例如,必须有更好的方法来指定参数operation而不是像plus或条件那样的字符串。

I need this function to be rewritten in a better way, more professionally and works as described. 我需要以更好的方式重写这个功能,更专业,并按照描述工作。

Thanks in advance. 提前致谢。

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 一个工作示例https://jsbin.com/rahomorupa/4/edit?html,js,console,output

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: 基于Joe的回答,我建议你将plusminus常量分别定义为+1-1以简化增量/减量逻辑,以及模数运算符来处理数组环绕:

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: %运算符返回除法的余数,当与数组长度的数组索引一起使用时,它可以方便地循环回0:

 const array = ['first', 'second', 'third']; for (let i = 0; i < 20; i++) { console.log(array[i % array.length]); } 

You can pass a Boolean for plus , use an arrow function, and a ternary operator: 您可以传递一个plus的布尔值,使用箭头函数和三元运算符:

 var MyArray = ["Music1", "Music2", "Music3", "Music4"]; var currentMusic = "Music1"; $(".increase").on('click tap', nextMusic); $(".decrease").on('click tap', previousMusic); function nextMusic() { unaryChange(true) } function previousMusic() { unaryChange(false) } function unaryChange(plus) { currentMusic = currentMusic == "Music4" ? "Music1" : (currentMusic == "Music0" ? "Music4" : currentMusic); currentMusic = currentMusic.replace(/\\d+$/, n => plus ? ++n : --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> 

I think this is a good start. 我认为这是一个好的开始。 Accessing the indices of the array versus the values feels a lot cleaner. 访问数组的索引与值相比感觉更清晰。 Using ternaries cleans up a lot of logic into one line as well. 使用三元组也可以将大量逻辑清理成一行。

 var MyArray = ["Music1", "Music2", "Music3", "Music4"]; var currentMusic = 0; $(".increase").on('click tap', unaryChange); $(".decrease").on('click tap', unaryChange); function unaryChange() { if (event.target.className === "increase") { currentMusic = (currentMusic < 3 ? currentMusic + 1 : 0) } else { currentMusic = (currentMusic > 0 ? currentMusic -= 1 : 3) } console.log(MyArray[currentMusic]); $(".text").text(MyArray[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> 

Here's how I'd do it. 这是我怎么做的。 Since it seems that the word Music is just a prefix used to designate a particular unit, I wont store it over and over again in a array. 因为似乎音乐这个词只是用于指定特定单元的前缀,所以我不会在数组中反复存储它。 As for jQuery? 至于jQuery? Yeah, nah. 是的,不。

 "use strict"; function byId(id){return document.getElementById(id)} window.addEventListener('load', onLoaded, false); function onLoaded(evt) { let prefix = 'Music'; let count = 4, index=0; byId('increase').addEventListener('click', function(evt){index++; index %= count; update();}, false); byId('decrease').addEventListener('click', function(evt){index--; if (index<0) index=count-1; update();}, false); function update() { byId('status').textContent = `${prefix}${index+1}`; } } 
 <span id='status'>Music1</span><br> <button id='increase'>+</button><button id='decrease'>-</button> 

Since you have an array of music, it's better to use that instead. 由于您有一系列音乐,因此最好使用它。 There's no need to operate from the text, you just need to update the array index to the next value and pass it to the function, and let it get the song name directly. 没有必要从文本操作,您只需要将数组索引更新为下一个值并将其传递给函数,并让它直接获取歌曲名称。

Since we want to be between the boundaries of 0 and the array length, here's what is used to do this: 由于我们希望介于0和数组长度的边界之间,因此以下是用于执行此操作的内容:

  • Get the next song: (currentTrackIndex + 1) % tracks.length . 获取下一首歌曲: (currentTrackIndex + 1) % tracks.length That will get the next index value and apply modulo to it so it will round back if it exceedes the array length. 这将获得下一个索引值并对其应用模数,因此如果它超出数组长度,它将回滚。
  • Get the previous song: (currentTrackIndex - 1 + tracks.length) % tracks.length . 获取上一首歌曲: (currentTrackIndex - 1 + tracks.length) % tracks.length It's pretty much the same as getting the next song, save for the case when the index it's already at zero. 它与获得下一首歌几乎相同,除了索引已经为零的情况。 If you apply modulo to a negative number, you will get a negative result and will mess up your array index. 如果将模数应用于负数,则会得到否定结果并且会使数组索引陷入混乱。 So instead of using a conditional clause (" if (currentTrackIndex === 0 ...) "), let's add the array length. 因此,不要使用条件子句(“ if (currentTrackIndex === 0 ...) ”),而是添加数组长度。 Why? 为什么? Because since 0 % n == 0 and n % n == 0 , adding the array length will not change the modulo result, while keeping your index as a positive number. 因为0 % n == 0n % n == 0 ,所以添加数组长度不会改变模数结果,同时保持索引为正数。

(I changed the name from MyArray to tracks and unaryChange to changeTrack , to give it better meaning clarity) (我将名称从MyArray更改为tracks ,将unaryChangechangeTrack ,以更好地表达清晰度)

var tracks = ["Music1", "Music2", "Music3", "Music4"];

var currentTrackIndex = 0;

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

function nextMusic() {
  //It will move to the next track. If it's over the array length, it will reset to 0
  changeTrack((currentTrackIndex + 1) % tracks.length)
}

function previousMusic() {
  //It will move to the previous song. If it's below zero, it will reset to the last track index
  changeTrack((currentTrackIndex + tracks.length - 1) % tracks.length)
}

function changeTrack(newTrackIndex) {
  currentTrackIndex = newTrackIndex;
  var currentTrack = tracks[currentTrackIndex];
  console.log(currentTrackIndex);
  $(".text").text(currentTrack);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM