Javascript 从包含姓名的字符串中获取姓名的首字母和全名

Javascript 从包含姓名的字符串中获取姓名的首字母和全名,javascript,regex,ecmascript-6,Javascript,Regex,Ecmascript 6,假设有一些字符串包含不同格式的名称(每行可能是用户输入): 我需要转换这些名称以获得格式Lastname ABC。因此,每个surename都应该转换为其首字母,并附加到lastname 这个例子应该导致 Guilcher GM, Harvey M, Hand JP Liesner R, Collins PT, Richards M Manco-Johnson M, Santagostino E, Ljung R 问题在于不同的(可能的)输入格式。我认为我的尝试不太明智,所以我要求 优化转换代

假设有一些字符串包含不同格式的名称(每行可能是用户输入):

我需要转换这些名称以获得格式
Lastname ABC
。因此,每个surename都应该转换为其首字母,并附加到lastname

这个例子应该导致

Guilcher GM, Harvey M, Hand JP
Liesner R, Collins PT, Richards M
Manco-Johnson M, Santagostino E, Ljung R
问题在于不同的(可能的)输入格式。我认为我的尝试不太明智,所以我要求

  • 优化转换代码的一些提示
  • 我怎么把它们放在一个函数中呢?我想首先我必须测试字符串的格式是
  • 让我来解释一下我是如何解决这个问题的:

    第一个示例字符串

    在第一个示例中,首字母后面跟着一个点。应该删除点,并且应该删除名称和初始值之间的逗号

    firstString
      .replace('.', '')
      .replace(' &', ', ')
    
    我想我确实需要一个正则表达式来获取名称后面和首字母前面的逗号

    第二个示例字符串

    在第二个示例中,名称应按空格分隔,最后一个元素作为lastname处理:

    const elm = secondString.split(/\s+/)
    const lastname = elm[elm.length - 1]
    const initials = elm.map((n,i) => {
      if (i !== elm.length - 1) return capitalizeFirstLetter(n)
    })
    
    return lastname + ' ' + initals.join('')
    
    ……不太优雅

    第三个示例字符串


    第三个示例的格式已经正确-只需删除末尾的点。因此,不必对该输入做任何其他操作。

    给定您的示例数据,我将尝试根据名称部分计数=2进行猜测,因为很难依赖任何
    &
    \n
    -这意味着将它们都视为

    请针对您的数据尝试此方法,并让我知道此方法失败的任何用例,因为我非常有信心此脚本在某个时候会因更多数据而失败:)

    let testString=“Guillcher,G.M.,Harvey,M.&Hand,J.P.\nRi Liesner,Peter Tom Collins,Michael Richards\n Manco Johnson M,Santagostino E,Ljung R.”;
    常量inputOarray=i=>i
    .替换(/\/g,“”)
    .替换(/[\n&]/g,“,”)
    .替换(/?,?/g,“,”)
    .split(',');
    const reducer=函数(累加器、值、索引、数组){
    设pos=累加器长度-1;
    让名称=value.split(“”);
    如果(names.length>1){
    累加器。推送(名称);
    }否则{
    如果(累加器[pos]。长度>1)累加器[++pos]=[];
    累加器[pos]。推送(值);
    }
    返回累加器.filter(n=>n.length>0);
    };
    
    log(inputOarray(testString).reduce(reducer,[]])如果不调用多个
    replace()
    方法,这是不可能的。提供的解决方案中的步骤如下:

    • 删除缩写名称中的所有点
    • 用firstname替换lastname
    • 将姓氏替换为其开头字母
    • 删除不需要的字符
    演示:

    var s=`Guillcher,G.M.,Harvey,M.和Hand,J.P。
    李斯纳、彼得·汤姆·柯林斯、迈克尔·理查兹
    曼科·约翰逊M,桑塔戈斯蒂诺E,容格R`
    //删除缩写名称中的所有点
    变量b=s.replace(/\b([A-Z])\./g,“$1”)
    //替换名字和姓氏
    。替换(/([A-Z][\w-]+(?:+[A-Z][\w-]+)*)+([A-Z][\w-]+)\b/g,($0,$1,$2)=>{
    //用首字母替换全名
    返回$2+“”+$1。替换(/\b([A-Z])\w+*/g,“$1”);
    })
    //删除不需要的前/后逗号和符号
    .替换(/(,)+([A-Z]+)\b*[,&]?/g,“$2$1”);
    
    控制台日志(b)这是我的方法。我试图保持简短,但要获得边缘案例,复杂度出人意料地高

    • 首先,我格式化输入,替换
      ,并删除
    • 然后,我将输入拆分为
      \n
      ,然后是
      ,最后是
      (空格)
    • 接下来我要处理块。在每个新段(由
      分隔)上,我处理上一段。我这样做是因为我需要确保当前段不是初始段。如果是这样的话,我会尽我所能跳过最初的部分,处理上一个部分。前一个将有正确的首字母和姓氏,因为我有我需要的所有信息
    • 如果有片段的话,我会得到片段的首字母。这将在下一段开始时用于处理当前段
    • 在完成每一行之后,我再次处理最后一段,因为它不会被称为其他
    我知道如果不使用regexp,复杂性很高,使用状态机来解析输入可能会更好

    const isInitial=s=>[…s].every(c=>c==c.toUpperCase());
    const generateInitial=arr=>arr.reduce((a,c,i)=>a+(i{
    如果(!首字母){
    初始=生成初始(单词);
    }
    常量姓氏=单词[words.length-1];
    返回{首字母,姓氏};
    }
    const doDisplay=x=>x.map(x=>x.lasname+''+x.initial).join(',');
    const doProcess=\u=>{
    const formatted=input.value.replace(/\./g',).replace(/&/g',,);
    const chunks=formatted.split('\n').map(x=>x.split(',').map(x=>x.trim().split(''));
    常数=[];
    chunks.forEach(行=>{
    设lastSegment=null;
    设lastInitial=null;
    设lastInitialOnly=false;
    line.forEach(段=>{
    如果(最后一段){
    //如果段只包含一个首字母,则它是对应的首字母
    //上一节
    const initialOnly=segment.length==1&&i初始(段[0]);
    如果(仅首字母){
    lastInitial=段[0];
    }
    //避免处理仅为首字母的最后一段
    //这样可以防止两次添加段
    如果(!lastInitialOnly){
    //如果段不是首字母,我们需要生成首字母
    //对于上一段,如果它还没有
    
    const elm = secondString.split(/\s+/)
    const lastname = elm[elm.length - 1]
    const initials = elm.map((n,i) => {
      if (i !== elm.length - 1) return capitalizeFirstLetter(n)
    })
    
    return lastname + ' ' + initals.join('')