【问题标题】:Need help to reverse a string of words需要帮助扭转一串单词
【发布时间】:2018-02-07 17:35:49
【问题描述】:

当我在函数中传递以下字符串作为参数时,如何获得以下输出?

  • 输入:"Reverse this line"

  • 输出:"esreveR siht enil"

这是我的代码

function reverseWords(string) {
    var wordArray = string.split(" ");
    var resultWordArray = [];
    var requiredSentance;
    wordArray.forEach(word => {
        if (word == " ") {
            var space = " ";
            resultWordArray.push(space);
        } else {
            var SplittedWord = word.split("");
            var reversedWordsLettersArray = [];
            SplittedWord.forEach(letter => {
                reversedWordsLettersArray.unshift(letter);
                var reversedWord = reversedWordsLettersArray.join("");
                resultWordArray.push(reversedWord);
            })
        }
    })
    var resultSentance = resultWordArray.join(" ");
    console.log(resultSentance);
}
reverseWords("Reverse this line");

将其作为输出返回:

"R eR veR eveR reveR sreveR esreveR t ht iht siht l il nil enil"

我在这里错过了什么?

【问题讨论】:

  • 你错过了Array.prototype.reverse()已经存在的事实:function reverseWords (string) { return string.split(' ').map(word => Array.from(word).reverse().join('')).join(' '); }

标签: javascript arrays algorithm ecmascript-6


【解决方案1】:

您可以将字符串拆分为单词并映射每个单词,将其拆分为字符数组并反转数组,然后将单词重新组合成单​​个字符串。像这样:

string.split(' ').map(s => s.split('').reverse().join('')).join(' ')

解释代码:

string.split(' ')

这一行将整个字符串拆分为单词数组,"Reverse this line" 变为 ["Reverse", "this", "line"](注意空格已消失)。请记住,双空格仍会被拆分为一个空格。

由于我们现在有一个数组,您可以使用.map 函数迭代整个字符串。它的工作方式类似于您尝试使用.forEach 的方式,不同之处在于.map 函数将返回一个新数组,其中包含在.map 回调函数的每次迭代中返回的修改值。确保返回一些东西,否则值将是undefined!如上例所示,ES2015+ 中的箭头函数具有隐式返回,但如果您要使用 => {...},则该块需要显式的 return 语句才能工作。

.map函数回调的代码

s => s.split('').reverse().join('')

接收s,这是来自上述数组的单个单词,将单词按空字符串拆分,这是将字符串拆分为字符的解决方法。例如,"Reverse" 变为 ["R", "e", "v", "e", "r", "s", "e"].reverse() 函数的名称非常具有描述性,它只是反转数组。不过要小心!它会改变数组,因此如果您在随机数组上调用 .reverse() 函数,它将从该行开始反转。如果您不小心,这可能会导致一些问题。最后,.join('') 将反转的字符数组放回单个字符串单词中。

最后,最后的 .join(' ') 将映射数组(现在包含反转的单词)与中间的空格一起放回原处,类似于 .join('') 将字符数组放回单个单词的方式。

【讨论】:

  • 您可以使用正则表达式使其更简单:str.match(/./g).reverse().join('')
  • @Pedro 如果有两个连续的空格会抛出错误。
  • @PatrickRoberts 怎么样?它似乎对我有用。我使用的是 Chrome 版本 63。
  • @Pedro 这与您的测试方式相似吗? "Reverse this line".split(' ').map(s => s.match(/./g).reverse().join('')).join(' ')
  • @Pedro 这不能正常工作。再仔细看看预期的输出。 OP 希望还原每个单词,而不是整个字符串。
【解决方案2】:

具体使用您的代码,您将非常接近您想要做的事情。您只需将reversedWord 变量的声明移出forEach 循环,在forEach 循环内更新,最终将使用整个反向单词定义。

function reverseWords(string) {

var wordArray = string.split(" ");
var resultWordArray = [];
var requiredSentance;

wordArray.forEach(word => {

  if (word == " ") {
    var space = " ";
    resultWordArray.push(space);

  } else {
    var SplittedWord = word.split("");
    var reversedWordsLettersArray = [];
    var reversedWord; //define variable here 

    SplittedWord.forEach(letter => {
      reversedWordsLettersArray.unshift(letter);
      reversedWord = reversedWordsLettersArray.join("");
    })
    resultWordArray.push(reversedWord); // push it here
  }
})

var resultSentance = resultWordArray.join(" ");
  console.log(resultSentance);
}


reverseWords("Reverse this line");

【讨论】:

    【解决方案3】:

    这是一个有趣的方法,不需要调用.map(),如果您跳出框框思考一下字符串处理:

    function reverseWords(string, delimiter = ' ') {
      return string
        .split('').reverse().join('')
        .split(delimiter).reverse().join(delimiter);
    }
    
    console.log(reverseWords('Reverse this line'));

    如果您在第一遍中逐个字符地反转,则可以通过单词分隔符(在本例中为' ')拆分字符串,并在第二遍中将单词反向以将它们放回原始顺序.

    在对这种方法进行基准测试后,我发现it is twice as fast as the currently accepted answer

    此函数的另一个不错的功能是您可以将单词分隔符指定为可选的第二个参数:

    function reverseWords(string, delimiter = ' ') {
      return string
        .split('').reverse().join('')
        .split(delimiter).reverse().join(delimiter);
    }
    
    console.log(reverseWords('Reverse	this	line', '\t'));

    【讨论】:

    • 为什么不想使用.map
    • 我并没有说这是一件坏事,我只是通过强调方法的根本不同来将我的答案与当前答案区分开来。但是要回答您的问题,.map() 确实有每个单词的上下文切换开销,而这没有。我将进行基准测试并找出哪一个更快,因为也有可能两次通过可能仍然比一次通过开销慢。
    • 我很欣赏你的努力,但我看到的唯一一件事是与.split + .reverse + .join 一起玩得很好,在我看来,最终的结果是一个不太容易理解的代码.唯一真正的好处是可定制delimiter,如果此代码用于比问题中描述的更多不同的情况,这可能会很好。
    • @MarkoGrešak 我的假设是正确的,请查看the benchmark
    • 通常在可读性和性能之间进行权衡。这里的目标很简单。这个函数的用例可能不会出现在需要极端性能的代码库中,它看起来不像是这种问题。可能是这样,但在知道代码的某些部分的性能是问题之前,我认为性能优化而不是可读性是一个非论据。
    【解决方案4】:

    这是一个递归方法,只在字符串上迭代一次:

    function reverseWords(string){
      return (function f(str, i, reversed){
        if (!str[i])
          return reversed;
    
        if (str[i] == ' ')
          return reversed + ' ' + f(str, i + 1, '');
    
        return f(str, i + 1, str[i] + reversed);
      })(string, 0, '');
    }
    
    console.log(reverseWords("Reverse this line"));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-13
      • 1970-01-01
      • 2011-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-12
      相关资源
      最近更新 更多