如何在JavaScript中将字符串转换为脊柱形式?

7
我卡在了这个编码挑战上:脊柱病例。基本上我不知道如何使最后一个检查执行。
这是最后一个检查: spinalCase("AllThe-small Things") 应该返回 "all-the-small-things" 这是我的代码:
function spinalCase(str) {
    var outputString, 
              newstr,
              pattern1 = new RegExp(/[_\s]/, 'g'),
              pattern2 = new RegExp(/(?=[A-Z])/, 'g'),
              stringTest1 = pattern1.test(str),
              stringTest2 = pattern2.test(str);

         if(stringTest1)  {
                outputString = str.replace(pattern1, '-');
                newstr = outputString.toLowerCase();
          } else if(stringTest2) {
               str.split(/(?=[A-Z])/).join(' ');
                outputString = str.replace(pattern2, '-');
                newstr = outputString.toLowerCase();
          } else if (stringTest1 && stringTest2){
                outputString = str.replace(pattern1, '-');
                outputString = str.replace(pattern2, '-');
                newstr = outputString.toLowerCase();
          }

  return newstr;

}

我知道最后一个else if条件应该放在第一位,但我语法没写对。
提前感谢!
12个回答

7

以下是我建议的做法:

function sp(str) {
  var spinal = str.replace(/(?!^)([A-Z])/g, ' $1')
                .replace(/[_\s]+(?=[a-zA-Z])/g, '-').toLowerCase();
  return spinal 
}

JsBin 示例

就你的代码而言,你检查了:

如果 test1 else if test2,然后 else if test1 and test2,逻辑不正确:

你可以尝试在第一个 if 检查中添加 !test2!test1 以使其工作:

if (stringTest1 && !stringTest2)...

编辑:

这里是如何使您的代码在最后一个 else if 中触发,我在其中放置了一个 console.log 来向您展示:

JSBin 示例

function spinalCase(str) {
    var outputString, 
              newstr,
              pattern1 = new RegExp(/[_\s]/, 'g'),
              pattern2 = new RegExp(/(?=[A-Z])/, 'g'),
              stringTest1 = pattern1.test(str),
              stringTest2 = pattern2.test(str);

         if(stringTest1 && !stringTest2)  {
                outputString = str.replace(pattern1, '-');
                newstr = outputString.toLowerCase();
          } else if(!stringTest1 && stringTest1) {
               str.split(/(?=[A-Z])/).join(' ');
                outputString = str.replace(pattern2, '-');
                newstr = outputString.toLowerCase();
          } else if (stringTest1 && stringTest2){
                console.log('were in the last else!!!');
                outputString = str.replace(pattern1, '-');
                outputString = str.replace(pattern2, '-');
                newstr = outputString.toLowerCase();
          }

  return newstr;

}

我无法理解如何将您的见解融入我的代码,但我非常感谢您提供的解决方案。非常优雅。我需要深入研究您的解决方案。虽然我认为我已经明白了。我不知道您可以像那样链接方法。非常感谢您的帮助,Jordan! - Antonio Pavicevac-Ortiz
非常感谢,但是它必须关闭,因为它不能完全工作。 最后一个条件确实触发了,但总体上该函数与您的答案产生的结果不同。 说到这个,您介意解释一下您的解决方案是如何做的吗? 我的理解是: 首先,您使用replace来检查第一个表达式 - 它检查任何大写字符A-Z,但(?!^)$1是什么?我猜您将它们包装在(...)中使它们成为表达式,因为如果您没有这样做,解释器可能会返回错误? - Antonio Pavicevac-Ortiz
第二个替换 .replace(/[_\s]+(?=[a-zA-Z])/g, '-') 首先检查 _ 和空格字符,然后似乎你在说让我们连接 (?=[a-zA-Z])/g, '-'),这是什么意思。提前致谢! - Antonio Pavicevac-Ortiz
嘿,有几个主要步骤,你已经掌握了大部分正确的内容,我建议你使用这个网站来分解和理解上面的内容:https://regex101.com/。如果你粘贴我使用的两个(不带 / /),你可以得到一个非常好的打印输出它们的功能!祝你好运。 - omarjmh

4

这是我的解决方案,简单易懂,使用正则表达式适用于所有情况。

function spinalCase(str) {
  return str.replace(/([A-Z])/g,' $1') /*Find all cap and add space at the start*/
        .replace(/[^A-Za-z0-9]/g,' ') /*Find all non alpha numeric and replace it with space*/
        .replace(/\s{1,}/g,"-") /*Convert all spaces to -*/
        .replace(/^\-|[\-]$/g,'') /*Slice - at the start and end*/
        .toLowerCase(); /*LowerCase it*/
}

3
function spinalCase(str) {
//Split the string at one of the following conditions 
        //a whitespace character [\s] is encountered
        //underscore character [_] is encountered
        //or by an uppercase letter [(?=[A-Z])]
//Join the array using a hyphen (-)
//Lowercase the whole resulting string 

   return str.split(/\s|_|(?=[A-Z])/).join('-').toLowerCase(); 

}

1

我也曾遇到这个问题,但找到了一个更简单的解决方案:

function spinalCase(str) {
  const regex =new RegExp(/(([A-Z]|[a-z])[a-z]+)/,'g');
  str=str.match(regex);
  return str.join('-').toLowerCase();
}

console.log(spinalCase('AllThe-small things'));


1

这是我的解决方案,正则表达式的使用较少:

function spinalCase(str) {
  var newStr = str[0];

  for (var j = 1; j < str.length; j++) {
    // if not a letter make a dash
    if (str[j].search(/\W/) !== -1 || str[j] === "_") {
      newStr += "-";
    }
    // if a Capital letter is found 
    else if (str[j] === str[j].toUpperCase()) {
      // and preceded by a letter or '_'
      if (str[j-1].search(/\w/) !== -1 && str[j-1] !== "_") {
        // insert '-' and carry on
        newStr += "-";
        newStr += str[j];
      }
      else {
        newStr += str[j];
      }
    }
    else {
        newStr += str[j];
    }
  }

  newStr = newStr.toLowerCase();
  return newStr;
}

1
一个适合初学者的解决方案:
function spinalCase(str) {
//change camelCase to title case(i.e. change 'markIsHere' to 'Mark Is Here') 
    let newStr = str.replace(/([a-z])([A-Z])/g, ('$1 $2'));
//replace space with '-'
    newStr = newStr.replace(/ /g, '-');
//replace underscores with '-'
    newStr = newStr.replace(/_/g,'-');
//change the result to lowercase
    return newStr.toLowerCase()
}

请不要仅仅发布代码作为答案,还要提供代码的解释以及它是如何解决问题的。带有解释的答案通常更有帮助和更高质量,并且更有可能吸引赞同。 - Ran Marciano

1
function spinalCase(str) {

  // any string followed by upperCase letter
  var  re = /(?=[A-Z])/g;  

  // any string followed by space and upperCase/lowerCase letter 
  var  re2=/(?=\s[A-Z]|\s[a-z])/g;

  // any string of 2 or more '-'
  var re3 = new RegExp("-{2,}", "g");

  var space = new RegExp(" ","g");
  var hyphen = new RegExp("_","g");

  str = str.replace(hyphen,"-");
  str = str.replace(re, '-');   
  str = str.replace(re2,"-");
  str = str.replace(re3,"-"); 
  str = str.replace(space,"");
  str = str.toLowerCase();
  if(str.slice(0,1)== '-'){
    str = str.replace("-","");  
  }     
  return str;
}

spinalCase('This Is Spinal Tap');

1
function spinalCase(str) {
  var newStr = '';
  var arr = str.split('');
  for (var i = 0; i < arr.length; i += 1) {
    if (i > 0) {
      if (arr[i] >= 'A' && arr[i] <= 'Z') {
        if (arr[i - 1] >= 'a' && arr[i - 1] <= 'z') {
          newStr += '-';
          newStr += arr[i].toLowerCase();
          continue;
        }
      }
      else if (arr[i] === ' ' || arr[i] === '_') {
        newStr += '-';
        continue;
      }
    }
    newStr += arr[i].toLowerCase();
  }
  return newStr;
}

spinalCase("AllThe-small Things");

0

虽然我不抱有任何人会在意的幻想,但是我会搜索单词之间的位置(由大写字母指示),并在那里放置连字符。例如:

const spinalCase = (str) => {
    let regex = /(?:\B|[ _])(?=[A-Z])/g;
    return str.replace(regex, '-').toLowerCase();
}

console.log(spinalCase('AllThe-small Things'));


0
function spinalCase(str) {

  // Create a variable for the white space and underscores
  var regex = /\s+|_+/g;

  // Replace low-upper case to low-space-uppercase
  str = str.replace(/([a-z])([A-Z])/g, '$1 $2');

  // Replace space and underscore with dashes
  return str.replace(regex, '-').toLowerCase();

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接