【问题标题】:Taking a string and reversing certain words -- Javascript取一个字符串并反转某些单词——Javascript
【发布时间】:2023-03-31 08:54:01
【问题描述】:

编写一个函数,接收一个或多个单词的字符串,并返回相同的字符串,但所有五个或更多字母单词都颠倒了。传入的字符串将仅包含字母和空格。仅当出现多个单词时才会包含空格。

我写的代码反转了整个字符串。我相信它与 if 语句有关,它不会捕获大于 5 的单词。我在编写代码时的想法是首先将字符串转换为单词数组,使用 for 循环遍历数组并找到单词大于 5,然后反转大于 5 的单词。我发现了类似的问题,这就是我寻求帮助的程度。我被卡住了,任何帮助将不胜感激!我是编码和学习 Javascript 的新手。

function spinWords(backward){

 var sentence = "";
 var separate = backward.split("");

 for (var i = separate.length - 1; i >= 0; i--){
   if (separate[i].length >= 1){
   sentence += separate[i].split("").reverse().join("");
   }
  else {
  sentence += "" + separate[i];
  }
 }
return sentence;
}

spinWords("Hey fellow warriors");

【问题讨论】:

  • 您的问题陈述不是 100% 清楚的。您是说只想反转 5 个字符或更长的单词吗?

标签: javascript arrays string


【解决方案1】:

如果您使用正则表达式匹配一行中的 5 个或更多单词字符,并使用替换函数 reverse 他们,您可能会发现逻辑要容易得多:

function spinWords(backward) {
  return backward.replace(/\w{5,}/g, word => word.split('').reverse().join(''));
}

console.log(spinWords("Hey fellow warriors"));

要修复您的代码,您应该将输入字符串(名为 backward 的变量)拆分为 空格,而不是空字符串,以获取单词数组,然后对其进行迭代数组(从开头开始,而不是结尾),检查每个单词的length 并与sentence 连接:

function spinWords(backward) {

  var sentence = "";
  var separate = backward.split(" ");
  
  for (var i = 0; i < separate.length; i++) {
    if (sentence) sentence += ' ';
    if (separate[i].length >= 5) {
      sentence += separate[i].split("").reverse().join("");
    } else {
      sentence += separate[i];
    }
  }
  return sentence;
}

console.log(spinWords("Hey fellow warriors"));

【讨论】:

    【解决方案2】:

    以下是关于解决此问题的可能方法的讨论。对于这么简单的问题,这不是我可能会做的,但它展示了一种思维方式,可以更轻松地解决许多问题,并在你这样做时重用你的工作。


    解决问题

    您想在这里做几件事,因此将问题分解为多个步骤可能会有所帮助。

    从根本上说,您想要颠倒某些单词。那么为什么不写一个函数来做到这一点呢?应该很简单。这是一个版本:

    const reverseWord = word => word.split('').reverse().join('')
    reverseWord('word') //=> 'drow'
    

    但您只想对长度至少为 5 的单词执行此操作。我们可以使用它来编写更复杂的函数,而不是重写我们现有的函数:

    const reverseIfGte5 = word => word.length >= 5 ? reverseWord(word) : word
    reverseIfGte5('word') //=> 'word'
    reverseIfGte5('supercalifragilisticexpialidocious')
    //=> 'suoicodilaipxecitsiligarfilacrepus')
    

    注意这里,我们写reverseIfGte5 使用 reverseWord。所以我们的reverseWord 函数也可以根据我们的选择被重用,而且每个函数都在做一些简单的事情。

    我们现在可以用这个函数写spinWord,通过

    const spinWords = sentence => sentence.split(/\s+/).map(reverseIfGte5).join(' ')
    
    spinWords('Hey fellow warriors') //=> 'Hey wollef sroirraw'
    

    这符合预期。这可能是一个停下来的好地方。不过……

    每个函数只做一件事

    我们上面的spinWords函数负责两件事:

    • 在句子中查找单词
    • 将我们的反转功能应用于每个

    理想情况下,一个函数应该只负责一件事。 (当然,在决定如何分解这些责任时需要做出一些判断。)

    将其分开可能会很有用。我们可以通过不同的方式做到这一点。这是一个简单的:

    const updateWords = wordFn => sentence => sentence.split(/\s+/).map(wordFn).join(' ')
    const spinWords = updateWords(reverseIfGte5)
    

    现在我们有了一个可重用的函数,我们可以使用它,例如,一个明显的 capitalizeFirstLetter 函数,如下所示:

    const titleCase = updateWords(capitalizeFirstLetter)
    titleCase('Hey fellow warriors') //=> 'Hey Fellow Warriors')
    

    修复错误

    我们的代码现在看起来像这样:

    const updateWords = wordFn => sentence => sentence.split(/\s+/).map(wordFn).join(' ')
    const reverseWord = word => word.split('').reverse().join('')
    const reverseIfGte5 = word => word.length >= 5 ? reverseWord(word) : word
    const spinWords = updateWords(reverseIfGte5)
    

    这些函数从最有可能被重用到最不可能被重用。

    请注意,这里的总代码,当使用这样的可重用函数时,比这个普通版本要长一点:

    const spinWords = sentence => sentence.split(/\s+/).map(
      word => word.length >= 5 ? word.split('').reverse().join('') : word
    ).join(' ')
    

    但我们的版本有几个优点。显然,可重用性是其中之一。但另一个问题是,将问题分解成小块后,如果我们发现问题,我们就知道去哪里寻找解决方案。

    你猜怎么着,这个解决方案实际上有一个潜在的错误。

    如果我们用'Hey fellow warriors' 调用这个函数,我们会返回'Hey wollef oirraw' 而不是预期的'Hey wollef sroirraw'。我们的间距已关闭。

    因为这个问题被分解成不同的功能,所以毫无疑问我们需要更改哪个功能才能解决这个问题。显然,它是负责将句子拆开并重新组合在一起的功能,updateWords。有一个简单的解决方法,从

    const updateWords = wordFn => sentence => sentence.split(/\s+/).map(wordFn).join(' ')
    

    const updateWords = wordFn => sentence => sentence.split(' ').map(wordFn).join(' ')
    

    但我们最好使用来自CertainPerformance的答案的变体,并像这样重写它:

    const updateWords = wordFn => sentence => sentence.replace(/\w+/g, wordFn)
    

    这修复了错误,实际上处理的案例比我们最初处理的要多。 (注意它现在也处理标点符号):

    spinWords('Hey, fellow warriors!') //=> 'Hey, wollef sroirraw!'
    

    重要的一点是,为了修复我们的错误,我们能够隔离负责的函数并在不更改任何其他内容的情况下对其进行更改。

    工作代码

    这就是我们得到的结果:

    const updateWords = wordFn => sentence => sentence.replace(/\w+/g, wordFn)
    const reverseWord = word => word.split('').reverse().join('')
    const reverseIfGte5 = word => word.length >= 5 ? reverseWord(word) : word
    
    const spinWords = updateWords(reverseIfGte5)
    
    console.log(spinWords('Hey, fellow warriors!'))

    我们将问题分解为两个相当可重用的函数(reverseWordupdateWords),以及两个非常针对我们的问题的函数(reverseIfGte5spinWords。)每个都有明确定义的职责,并且它们很容易单独测试。

    进一步扩展

    这是我可能会使用这样的功能。但是因为我的个人库经常包含一个函数when,它已经是其中一个的泛化,所以有时我可能更愿意在此基础上进行构建:

    const when = (cond, then) => val => cond(val) ? then(val) : val
    const reverseIfGte5 = when(word => word.length >= 5, reverseWord)
    

    我创建了when,因为有时我想在某些条件为真时使用我的输入的更改版本,而在条件为假的情况下使用原样。这正是reverseIfGte5 需要做的事情,因此在when 之上构建它很有用。

    这就是实用程序库的构建方式。几个具体问题有明显的联系,写了更通用的解决方案来处理它们。如果这些这样的解决方案足够通用,那么它们就是包含在您的个人库或团队库中的候选者。如果它们对更广泛的受众有用,它们可能会被包含在通用实用程序库中。

    我是Ramda 的作者之一,这是一个用于 JS 函数式编程的实用程序库,而这正是它的构建方式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-01-02
      • 1970-01-01
      • 2021-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多