使条件函数更高效

Posted

技术标签:

【中文标题】使条件函数更高效【英文标题】:Making a conditional function more efficient 【发布时间】:2019-10-10 14:22:12 【问题描述】:

我想创建一个根据给定参数修改变量的函数。

该函数检查一个变量和该字符串中的数字。然后通过参数,我指定将数字增加或减少 1 (++1)。

还有一个数组,如果数字等于数组的长度,则变为1,如果数字小于1,则等于数组的大小。这是为了确保字符串的数量不小于 1 或大于数组的长度。

带有数字的字符串是Music1。所以这个圈子就像: ...., 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>

上述方法几乎可以完成工作,但是我正在寻找一种更简单、更专业的解决方案。它看起来效率不高。例如,必须有更好的方法来指定参数operation,而不是像plus 这样的字符串或条件。

我需要以更好的方式、更专业的方式重写此函数并按照描述的方式工作。

提前致谢。

【问题讨论】:

【参考方案1】:

您可以为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>

【讨论】:

【参考方案2】:

在Joe's answer 的基础上,我建议您将plusminus 的常量分别定义为+1-1,以简化递增/递减逻辑,同时使用the modulus operator 来处理数组换行-周围:

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);

% 运算符返回除法的余数,当与数组索引一起用于数组长度时,它可以方便地循环回 0:

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

for (let i = 0; i < 20; i++) 
  console.log(array[i % array.length]);

【讨论】:

好主意,但如果当前索引为 0 并且在这种情况下将减号发送到函数 -1 % 4 为 -1,它将不起作用 已更新以处理负索引。【参考方案3】:

最好使用数组索引而不是值

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);

在这种情况下,无论数组大小如何,它都可以工作。

一个工作示例https://jsbin.com/rahomorupa/4/edit?html,js,console,output

【讨论】:

【参考方案4】:

我认为这是一个好的开始。访问数组的索引与值相比感觉要干净得多。使用三元组也可以将大量逻辑清理到一行中。

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>

【讨论】:

【参考方案5】:

这就是我的做法。由于 Music 这个词似乎只是一个用于指定特定单元的前缀,所以我不会一遍又一遍地将它存储在一个数组中。 至于 jQuery?是的,不。

"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>

【讨论】:

【参考方案6】:

由于您拥有一系列音乐,因此最好使用它。无需从文本中操作,只需将数组索引更新为下一个值并传递给函数,让它直接获取歌曲名称即可。

由于我们想要介于 0 和数组长度的边界之间,所以我们可以这样做:

获取下一首歌曲:(currentTrackIndex + 1) % tracks.length。这将获得下一个索引值并对它应用模数,因此如果它超过数组长度,它将返回。 获取上一首歌曲:(currentTrackIndex - 1 + tracks.length) % tracks.length。这与获取下一首歌曲几乎相同,除了索引已经为零的情况。如果您对负数应用模数,您将得到一个负数结果并且会弄乱您的数组索引。因此,让我们添加数组长度,而不是使用条件子句(“if (currentTrackIndex === 0 ...)”)。为什么?因为从0 % n == 0n % n == 0 开始,添加数组长度不会改变模结果,同时保持索引为正数。

(我将名称从MyArray 更改为tracksunaryChange 更改为changeTrack,以使其含义更清晰)

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);

【讨论】:

以上是关于使条件函数更高效的主要内容,如果未能解决你的问题,请参考以下文章

如何使一个函数具有三种不同的输出条件?

使 SQL Server 中的正则表达式搜索更高效

SQL里if语句和case语句有啥区别吗?哪个使用更高效?就是查询更优化?