通过多个函数运行一个值(Javascript)

Posted

技术标签:

【中文标题】通过多个函数运行一个值(Javascript)【英文标题】:Run one value through multiple functions (Javascript) 【发布时间】:2018-06-29 04:42:38 【问题描述】:

我想创建一个函数“palindromes()”来检查一个值是否是回文(向前和向后拼写相同)。 为此,我创建了 4 个函数,其中:

    使所有字母变小 删除所有非字母字符 反转随后的数组,最后... 检查该数组是否为回文。

查看以下函数:

  function makeSmall(input) 
    lowerCase = input.toLowerCase();
    return lowerCase;
  

  function keepOnlyLetters(input) 
    var patt1 = /[a-z]/g;
    var onlyLetters = input.match(patt1);
    return onlyLetters;
  

  function reverseArray(array) 
    var reversedArray = array.slice().reverse();
    return reversedArray;
  

  function checkPalindromes(array) 
    var reversedArray = array.slice().reverse();
    for (let i = 0; i <= array.length; i++) 
      if (array[i] != reversedArray[i]) 
        return false;
      
    
    return true;
  

如何确保函数“palindromes()”采用一个值并在所有这些函数中运行它以最终给出该值是否为回文的答案(真或假)?

最好的问候, 贝尼

【问题讨论】:

您需要存储每个函数的返回值并将那个值传递给下一个。 reverseArraycheckPalindromes 中不用于反转数组时看起来毫无用处。 所以你想要keepOnlyLetters(makeSmall(str)),那么你需要将字符串更改为数组......所以,你可以reverseArray(keepOnlyLetters(makeSmall(str)).split('')).join('') 如果对这 4 个函数的需求不大,您可以将它们全部组合成一个并执行。 PS:我建议你找一个好的javascript教程。这个问题的提出和格式都很好,所以不赞成它会感觉不对,但通常我会做任何应该由一个体面的教程涵盖的问题。 In future versions of JS 你可以写类似str |&gt; makeSmall |&gt; keepOnlyLetters |&gt; checkPalindromes 的东西。但这仍然需要时间,语法可能仍然会改变。 【参考方案1】:

函数有一个收益递减点。当调用函数与使用内联函数的主体一样短时,您可能已经达到了这一点。例如,makeSmall(input) 与仅使用 input.toLowerCase() inline 相比并没有任何改进,而且会更慢且更难理解。 input.toLowerCase() 已经是一个函数;将它包装在另一个函数中只是浪费工作。

话虽如此,回答你的问题,因为你所有的函数都返回输入到下一个的值,你可以把你的函数放在一个数组中并调用reduce()

function palindromes(input) 
    return [makeSmall, keepOnlyLetters, reverseArray, checkPalindromes].reduce((a, c) => c(a), input)

【讨论】:

+1 表示diminishing returns with functionsreduce 的有趣用法,尽管我不确定它在可读性方面是否比仅仅编写它们更好。 你应该提到管道函数30secondsofcode.org/adapter#pipefunctionsconst pipeFunctions = (...fns) =&gt; fns.reduce((f, g) =&gt; (...args) =&gt; g(f(...args)));【参考方案2】:

因此,在开始尝试进行组合之前,有时最好按顺序进行,以确保您理解问题。随着你在作曲上的进步,你最终会知道使用什么工具。

function checkPalindrome(string)
 return string
  .toLowerCase()
  .match(/[a-z]/g)
  .reverse()
  .reduce(function ( acc, letter, index ) 
    return acc && string[index] == letter
  )


checkPalindrome('test') // false
checkPalindrome('tet') // true

好的,我们从程序上理解它并且知道有四个步骤。我们可以将这四个步骤拆分出来,但是由于两个步骤需要事先了解数组状态,并且我们不想引入convergelift,我们应该只使用pipe function 并结合以下步骤需要以前的状态。这样做的原因是函数最终会失去你可以使它们变得更小的多少,并且尝试将这些步骤分开不仅会损害可读性,还会损害可维护性。对于为该部分制作两个功能所付出的努力,这些并不是很好的回报!

function pipe (...fns)
  return fns.reduce( function (f, g)
    return function (...args)
      return g(
        f(...args)
      )
    
  

所有这个函数都是预先加载(组合)一堆函数以使一个函数的输出以left to right顺序(也称为数组顺序)应用于下一个函数的输入)。

现在我们只需要输出三个函数来管道:

function bringDown(string) return string.toLowerCase()  // ussually called toLower, see note

function onlyLetters(string) return string.match(/[a-z]/g) 

function flipItAndReverseItCompare(arrayLike)  // I like missy elliot... ok?
  let original = Array.from(arrayLike)
  return original
    .slice()
    .reverse()
    .reduce(function (acc, val, ind)
      return acc && val == original[ind]
    )

现在我们可以通过管道处理它们

let palindrome = pipe(
  bringDown,
  onlyLetters,
  flipItAndReverseItCompare
)

!palindrome('Missy Elliot') // true... and I never will be
palindrome('Te t') // true

现在您已经开始学习函数组合了!

【讨论】:

flipItAndReverseItCompare 中的错误应该是:return original.slice().reverse(),因为 reverse 会改变原始值并导致传递给它的所有字符串返回 true。【参考方案3】:

您可以像这样将函数调用串在一起......

var input = 'Racecar';

if (checkPalindromes(reverseArray(keepOnlyLetters(makeSmall(input))))) 
   alert("It's a palindrome");

【讨论】:

读起来太可怕了。您应该解释组成和一些设计模式,以使其更易于阅读 确实如此。我不会在实际项目中这样做。我只是展示了通过一系列函数传递单个值的最简单方法。【参考方案4】:

您可以以嵌套方式调用它们并在回文函数中返回最终结果。

示例代码:(在 cmets 中有更改)

function makeSmall(input) 
    // Added var to prevent it from being a global
    var lowerCase = input.toLowerCase();
    return lowerCase;


function keepOnlyLetters(input) 
    var patt1 = /[a-z]/g;
    var onlyLetters = input.match(patt1);
    return onlyLetters;


// This function is not really needed and is unused
/*function reverseArray(array) 
    var reversedArray = array.slice().reverse();
    return reversedArray;
*/

function checkPalindromes(array) 
    var reversedArray = array.slice().reverse();
    for (let i = 0; i <= array.length; i++) 
        if (array[i] != reversedArray[i]) 
            return false;
        
    
    return true;


// New Palindromes function
function palindromes(input)
    return checkPalindromes(keepOnlyLetters(makeSmall(input)));

注意:

你真的不需要这么多的功能来做到这一点。我把它放在这里作为对你确切问题的严格回答。此处的其他答案显示了如何以更短(更好?)的方式解决这个问题

【讨论】:

【参考方案5】:

尝试以下 sn-p。

    function makeSmall(input) 
        lowerCase = input.toLowerCase();
        return lowerCase;
    

    function keepOnlyLetters(input) 
        var patt1 = /[a-z]/g;
        var onlyLetters = input.match(patt1);
        return onlyLetters;
    

    function reverseArray(array) 
        var reversedArray = array.slice().reverse();
        return reversedArray;
    

    function checkPalindromes(array) 
        var reversedArray = array.slice().reverse();
        for (let i = 0; i <= array.length; i++) 
          if (array[i] != reversedArray[i]) 
            return false;
          
        
        return true;
    
    
    var result = checkPalindromes(reverseArray(keepOnlyLetters(makeSmall("Eva, Can I Stab Bats In A Cave"))));
    
    console.log(result);

注意函数是如何在一行中一个接一个地调用的。

【讨论】:

以上是关于通过多个函数运行一个值(Javascript)的主要内容,如果未能解决你的问题,请参考以下文章

通过 onchange 事件将 SELECT 的值传递给 Javascript 函数?

同一个函数通过设计模式在javascript中返回多个对象、数组或函数的值? [复制]

刷新页面并在之后运行函数 - JavaScript

javascript 内部函数的定义及调用

jQuery是什么?

预编译