再下划线后如何切割字符串?

时间:2019-09-11 17:55:20

标签: javascript string algorithm

我正在接收对象中的文件列表,我只需要在表中显示文件名及其类型。 所有文件均以timestamp_id_filename格式从服务器返回。

示例:1568223848_12345678_some_document.pdf

我写了一个辅助函数来剪切字符串。

首先,我使用String.prototype.split()方法做到了这一点,我使用了正则表达式,但随后又出现了问题。文件的名称中可以带有下划线,因此该文件不起作用,因此我还需要其他内容。我无法提出一个更好的主意。我认为它看起来真的很傻,整天都困扰着我。

函数如下:

const shortenString = (attachmentName) => {
    const file = attachmentName
        .slice(attachmentName.indexOf('_') + 1)
        .slice(attachmentName.slice(attachmentName.indexOf('_') + 1).indexOf('_') + 1);

    const fileName = file.slice(0, file.lastIndexOf('.'));
    const fileType = file.slice(file.lastIndexOf('.'));

    return [fileName, fileType];
};

我想知道是否有一种更优雅的方法可以不使用循环来解决问题。

8 个答案:

答案 0 :(得分:2)

您可以使用replacesplit,在这种模式下,我们将字符串替换为从字符串开头到第二个_的字符串,然后在.上拆分以获取名称和类型

enter image description here

let nameAndType = (str) => {
  let replaced =  str.replace(/^(?:[^_]*_){2}/g, '')
  let splited = replaced.split('.')
  let type = splited.pop()
  let name = splited.join('.')
  return {name,type}
}

console.log(nameAndType("1568223848_12345678_some_document.pdf"))
console.log(nameAndType("1568223848_12345678_some_document.xyz.pdf"))

答案 1 :(得分:1)

const re = /(.*?)_(.*?)_(.*)/;

const name = "1568223848_12345678_some_document.pdf";

[,date, id, filename] = re.exec(name);

console.log(date);
console.log(id);
console.log(filename);

一些注意事项:

  • 您想使正则表达式1次。如果这样做

    function getParts(str) {
      const re = /expression/;
      ...
    }
    

    然后,您每次调用getParts时都会创建一个新的正则表达式对象。

  • .*?.*

    这是因为.*是贪婪的,所以当正则表达式引擎看到它会将整个字符串的其余部分放入该插槽然后检查是否可以继续该表达式时。如果失败,则退出一个字符。如果失败,它将退出另一个字符,等等。另一方面,.*?会尽快得到满足。因此,它添加了一个字符,然后查看表达式的下一部分是否起作用,否则,它又添加了一个字符并查看表达式是否起作用,依此类推。

  • 拆分'_'可以,但是可能会产生许多临时字符串

    例如,如果文件名是1234_1343_a________________________.pdf

    假设速度很重要,您必须进行测试以查看使用常规扩展比拆分快还是慢。

答案 2 :(得分:1)


const getShortString = (str) => str.replace(/^(?:[^_]*_){2}/g, '')

对于像这样的输入 1568223848_12345678_some_document.pdf,它应该会给您类似some_document.pdf

的信息

答案 3 :(得分:0)

您可以有点链.indexOf以获得第二个偏移量和更多的偏移量,尽管两个以上看起来很丑。原因是indexOf将起始索引作为第二个参数,因此传递第一个匹配项的索引将帮助您找到第二个:

var secondUnderscoreIndex = name.indexOf("_",name.indexOf("_")+1);

所以我的解决方案是:

var index =  name.indexOf("_",name.indexOf("_")+1));
var [timestamp, name] = [name.substring(0, index), name.substr(index+1)];

或者,使用正则表达式:

var [,number1, number2, filename, extension] = /([0-9]+)_([0-9]+)_(.*?)\.([0-9a-z]+)/i.exec(name)
// Prints: "1568223848 12345678 some_document pdf"
console.log(number1, number2, filename, extension);

答案 4 :(得分:0)

我喜欢简单...

如果您需要时间日期,则将它们放在deleteAll([OneClass.self, AnotherClass.self]) [1]

[2]

答案 5 :(得分:0)

function splitString(val){
  return val.split('_').slice('2').join('_');
}

答案 6 :(得分:0)

如果文件名使用此格式timestamp_id_filename。您可以使用正则表达式跳过前两个'_'并保存nex一个。

测试:

var filename = '1568223848_12345678_some_document.pdf';
console.log(filename.match(/[^_]+_[^_]+_(.*)/)[1]); // result: 'some_document.pdf'

说明: / [^ ] + [^ ] + (。*)/

[^ ] +:取''的字符不同 :带有''字符 重复,这样两个“ _”被跳过 (。*):将字符保存到组中

match方法:返回数组,他的第一个元素是匹配表达式的捕获,接下来的元素是保存的组。

答案 7 :(得分:-1)

将文件名字符串分割为下划线的数组。 丢弃数组的前两个元素。 用下划线连接数组的其余部分。 现在您有了文件名。