除了最后一次出现,删除所有的出现?

31
我想要从一个字符串中删除所有子字符串=.,但保留最后一个子字符串。
例如:
1.2.3.4

应该变成:

123.4
9个回答

49

你可以使用正向预查来使用正则表达式,

"1.2.3.4".replace(/[.](?=.*[.])/g, "");

5
这应该是被采纳的答案。用英语来说,这个正则表达式的意思是“匹配所有在一个"."后面还有另一个"."的情况”,然后你只需要把它替换为空字符串。有时会听到人们抱怨正则表达式不如将一个大字符串切分成数组然后格式化可读性好,但是你可以在正则表达式上方的注释中简单地描述你的正则表达式。 - Josh from Qaribou
我认为过分依赖引擎无法智能优化的孤立性能测试并不明智,但正向预查似乎不能很好地扩展。在这里,我发现对于短字符串(例如“1.2.3.4”示例),它比拆分数组要快得多,但在较长的字符串上落后得多:https://jsperf.com/removing-all-but-last-string-token - Josh from Qaribou

18

两行代码:

function removeAllButLast(string, token) {
    /* Requires STRING not contain TOKEN */
    var parts = string.split(token);
    return parts.slice(0,-1).join('') + token + parts.slice(-1)
}

没有对字符串参数的要求的替代版本:

function removeAllButLast(string, token) {
    var parts = string.split(token);
    if (parts[1]===undefined)
        return string;
    else
        return parts.slice(0,-1).join('') + token + parts.slice(-1)
}

示例:

> removeAllButLast('a.b.c.d', '.')
"abc.d"
下面这个一行代码是一个正则表达式,利用了*通配符的贪婪性,同时replace函数如果没有找到匹配就不会改变原字符串。它的工作原理是匹配[最长包含点号的字符串][点号]并留下[剩余的字符串],如果找到匹配就从中去掉所有的'.':
'a.b.c.d'.replace(/(.*)\./, x => x.replace(/\./g,'')+'.')

(如果您的字符串包含换行符,则必须使用[.\n]而不是裸露的.)


仅供参考:如果有人需要去除除第一个之外的所有内容,则可以使用以下函数:function removeAllButFirst(string, token) { var parts = string.split(token); return parts.slice(0,1) + token + parts.slice(1).join(''); } - UsmanShabbir
2
如果字符串不包含令牌,则会添加。如需更多信息,请参阅文档。 - Ello
1
@Ello:感谢你找到了这个问题,我已经添加了修复并且还加入了一个正则表达式方法。 - ninjagecko

7
你可以像这样做:

你可以像这样做:

var str = '1.2.3.4';
var last = str.lastIndexOf('.');
var butLast = str.substring(0, last).replace(/\./g, '');
var res = butLast + str.substring(last);

Live example:


7
你可以使用正向先行断言(保留最后一个句点,如果有的话),并替换第一次出现的句点。

var string = '1.2.3.4';

console.log(string.replace(/\.(?=.*\.)/g, ''));


1
我找到了一种更好的方法来完成这个任务。下面是正确的replaceAllButLastappendAllButLast方法。后者在保留原始匹配的情况下进行替换。要删除,请将其替换为空字符串。

var str = "hello there hello there hello there"

function replaceAllButLast(str, regex, replace) {
  var reg = new RegExp(regex, 'g')
  return str.replace(reg, function(match, offset, str) {
      var follow = str.slice(offset);
      var isLast = follow.match(reg).length == 1;
      return (isLast) ? match : replace
  })
}

function appendAllButLast(str, regex, append) {
  var reg = new RegExp(regex, 'g')
  return str.replace(reg, function(match, offset, str) {
      var follow = str.slice(offset);
      var isLast = follow.match(reg).length == 1;
      return (isLast) ? match : match + append
  })
}

var replaced = replaceAllButLast(str, / there/, ' world')
console.log(replaced)

var appended = appendAllButLast(str, / there/, ' fred')
console.log(appended)

感谢 @leaf 提供的这些杰作,他在这里分享了它们。

1

replaceAllButLast函数比removeAllButLast函数更有用。当你想要删除时,只需替换为空字符串:

function replaceAllButLast(str, pOld, pNew) {
  var parts = str.split(pOld)
  if (parts.length === 1) return str
  return parts.slice(0, -1).join(pNew) + pOld + parts.slice(-1)
}

var test = 'hello there hello there hello there'
test = replaceAllButLast(test, ' there', '')

console.log(test) // hello hello hello there


0
function formatString() {
  var arr = ('1.2.3.4').split('.');
  var arrLen = arr.length-1;
  var outputString = '.' + arr[arrLen];
  for (var i=arr.length-2; i >= 0; i--) {
     outputString = arr[i]+outputString;
  }
  alert(outputString);
}

在这里查看它的运行效果:http://jsbin.com/izebay


0

var s='1.2.3.4';

s=s.split('.');
s.splice(s.length-1,0,'.');
s.join('');

123.4


0
你可以反转字符串,删除除第一个外的所有子字符串出现的位置,然后再次反转它以获得你想要的结果。

你觉得除了第一个之外删除所有出现的情况比另一种方式更容易吗? - Raynos
1
循环遍历字符串时,维护一个标志位以知道第一个已经过去了会更容易,然后我们就可以继续删除所有出现的内容。比使用str.charAt方法反向遍历字符串更加简单和可读。你可以始终使用str.lastIndexOf来记住最后一次出现的位置,但是随着你删除先前出现的任何子字符串,该位置会不断变化,因此需要重新计算。 - swapz83
一个反向循环比两个反转调用更好。 - Raynos

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