递归地将字符添加到字符串的末尾

时间:2020-03-20 15:14:03

标签: javascript recursion

我正在尝试递归解决此问题,但基本情况有些问题。我无法提出正确的基本案例。

如果单词以元音开头,则只需在末尾添加“ way”。

如果一个单词或一个单词簇不包含元音,只需在末尾添加“ ay”。

例如:translatePigLatin(“ california”)应该返回“ aliforniacay”。

translatePigLatin(“手套”)应该返回“ oveglay”。

translatePigLatin(“ algorithm”)应该返回“ algorithmway”。

function translatePigLatin(str) {
  var changed = true;

  if (!["a", "e", "i", "o", "u"].includes(str[0])) {

    return translatePigLatin(str.substring(1, str.length) + str[0])

  }
  else {
    return str + "ay"
  }
}

console.log(translatePigLatin("glove"));

5 个答案:

答案 0 :(得分:1)

尝试一下:

function translatePigLatin(str) {
  const vowels = ['a', 'e', 'i', 'o', 'u'];
  const chars = str.split('');
  const firstVowel = chars.findIndex(c => vowels.includes(c));
  // words beginning with a vowel are treated differently
  if (firstVowel === 0) {
    return str + 'way';
  } else {
    const start = str.substring(0, firstVowel);
    return str.substring(firstVowel) + start + 'ay';
  } 
}

console.log('glove:', translatePigLatin('glove'));
console.log('california:', translatePigLatin('california'));
console.log('algorithm:', translatePigLatin('algorithm'));

答案 1 :(得分:1)

为什么不只是使用类似这样的标志来区分第一个调用和其他递归调用

function translatePigLatin(str, isStart = false) {
  var changed = true;
  
  // to handle case when there's any vowels at start
  if(/^[aeiou]/i.test(str) && isStart){
    return str + 'way'
  }
  
  // to handle case when there's no vowels in string
  if(!/[aeiou]/i.test(str) && isStart){
    return str + 'ay'
  }
 
  if (!["a", "e", "i", "o", "u"].includes(str[0]) ) {
    return translatePigLatin(str.substring(1, str.length) + str[0])
  }
  else {
    return str + "ay"
  }
}

console.log(translatePigLatin("glove", true));
console.log(translatePigLatin("california", true));
console.log(translatePigLatin("algorithm", true));
console.log(translatePigLatin("gypsy", true));

答案 2 :(得分:1)

更新

好的,递归版本还不错。实际上,它可能几乎与下面的原始非递归解决方案一样干净。

const toPigLatin = (str, prefix) =>
  (!str) || 'aeiou' .includes (str [0]) 
    ? str + prefix + (prefix.length ? '' : 'w') + 'ay'
    : toPigLatin (str.slice(1), prefix + str[0])

const translatePigLatin = (str) => toPigLatin (str, '')
                            

console .log (['california', 'glove', 'algorithm', 'gypsy'] .map (translatePigLatin))

虽然也可以使用默认参数来编写不带辅助函数的代码,如下所示:

const translatePigLatin = (str, prefix = '') =>
  (!str) || 'aeiou' .includes (str [0]) 
    ? str + prefix + (prefix.length ? '' : 'w') + 'ay'
    : translatePigLatin (str.slice(1), prefix + str[0])

如果有人传递了其他参数,这会产生一些奇怪的效果,就像在调用map时发生的那样。

console .log (['california', 'glove', 'algorithm', 'gypsy'] .map (translatePigLatin))
//=> ["alifornia0cay","ove1glay","algorithm2way","3gypsyay"]

您可以通过在lambda中将参数包装到map来解决此问题,如下所示:

console .log (['california', 'glove', 'algorithm', 'gypsy'] .map (s => translatePigLatin(s)))
//=> ["aliforniacay","oveglay","algorithmway","gypsyay"]

但是您永远不能确定它不会引起问题。这种默认参数是一个长期存在的问题。

更新为更新

此替代方法可能会更干净:

const toPigLatin = (base, prefix, suffix) =>
  base .length == 0 || 'aeiou' .includes (base [0])
    ? base + prefix + suffix
    : toPigLatin (base .slice (1), prefix + base [0], 'ay')

const translatePigLatin = (str) => toPigLatin (str, '', 'way')

原始答案

(很快就过时了!)

这个非递归答案似乎比任何递归答案都更简单,更直接:

const translatePigLatin = str => {
  const idx = str .split ('') .findIndex (c => 'aeiou' .includes (c))
  return idx == 0
    ? str + 'way'
  : idx < 0
    ? str + 'ay'
  : // else 
    str .slice (idx) + str .slice (0, idx) + 'ay'
}

console .log (['california', 'glove', 'algorithm', 'gypsy'] .map (translatePigLatin))

(我们可能还需要一个.toLowerCase()。)

您是否正在寻找递归解决方案,是因为您认为这会更简单还是因为它似乎是问题的关键?

答案 3 :(得分:0)

这是纯递归(意味着该函数仅使用一个参数),但是要注意的是返回的值是结果的三个有序部分的元组:前缀,可能是移动到后缀的起始辅音,以及最后的后缀。

function f(s){
  if (s.length == 1){
    if (["a", "e", "i", "o", "u"].includes(s[0]))
      return [s[0], "", "way"];
    else
      return ["", s[0], "ay"];
  }
      
  const n = s.length;
  const [pfx, sfx1, sfx2] = f(s.slice(0, n-1));
  const last = s[n-1];
  
  if (pfx)
    return [pfx + last, sfx1, sfx2];
  else if (["a", "e", "i", "o", "u"].includes(last))
    return [pfx + last, sfx1, sfx2];
  else
    return [pfx, sfx1 + last, sfx2];
}

var strs = [
  "california",
  "glove",
  "algorithm",
  "gypsy"
];

for (let s of strs)
  console.log(s + ": " + JSON.stringify(f(s)));

答案 4 :(得分:0)

您可以使用滑动光标来解决问题;光标左侧的所有内容都尚未处理,右侧是所有辅音。有两种终端状态:

  1. 左侧以元音开头
  2. 左侧为空(单词仅包含辅音)

否则,辅音从左移到右,并且舞蹈从头开始。

实施

内部(命名)函数是递归的,而外部函数只是为第一次调用配置初始状态。

function translatePigLatin(s) {
  const vowels = 'aeiou'.split('')

  return function _translate(head, tail) {
    if (head == '' || vowels.includes(head[0])) {
      // head is empty for words without vowels
      // tail is empty on the first pass
      return head + tail + (tail ? 'ay' : 'way');
    }
    // move consonant to the tail
    return _translate(head.slice(1), tail + head[0]);
  }(s, '');
}

const words = [
  'california',
  'glove',
  'algorithm',
  'gypsy'
]
words.forEach(word => console.log(translatePigLatin(word)))

相关问题