【问题标题】:The most efficient way to trim a file name in JavaScript在 JavaScript 中修剪文件名的最有效方法
【发布时间】:2020-02-25 10:34:57
【问题描述】:

我想知道如何在 JS 中修剪文件名以在一定数量的字符后显示“...”或任何附件,这是处理所有可能的测试用例的最有效方法。

规则

  1. 显示实际的文件扩展名,而不是用“.”分割字符串名称后的最后一个字符
  2. 该函数应以输入文件名(字符串)、要修剪的字符数(整数)和附录(字符串)作为参数。
  3. 高效,我的意思是我希望编写更少的代码行并处理所有可能的边缘情况。

示例输入

  1. myAwesomeFile.min.css
  2. 我的真棒文件.tar.gz
  3. 文件.png

预期输出(比如说我想在 5 个字符后修剪)

  1. myAwe....min.css
  2. 我的 Aw....tar.gz
  3. 文件.png

编辑问题以展示我的尝试

function trimFileName(str, noOfChars, appendix) {
  let nameArray = str.split(".");
  let fileType = `.${nameArray.pop()}`;
  let fileName = nameArray.join(" ");

  if (fileName.length >= noOfChars) {
    fileName = fileName.substr(0, noOfChars) + appendix;
  };

  return (fileName + fileType);
}

console.log(trimFileName("myAwesomeFile.min.css", 5, "..."));
console.log(trimFileName("my Awesome File.tar.gz", 5, "..."));
console.log(trimFileName("file.png", 5, "..."));

编辑#2:如果您认为这不是标准预期,请随时继续编辑问题,并在示例输入和预期输出中添加更多边缘情况。

编辑#3:在新 cmets 之后为问题添加了更多细节。我知道我的尝试没有达到我的预期输出(我不确定我上面列出的输出是否是标准预期)。

编辑#4(最终版):删除了在 cmets 连续反弹后中间不断字的规则,并更改了规则以迎合更现实和实际的用例。

【问题讨论】:

  • 您有很多案例,甚至没有尝试完成其中一个?更不用说您正在寻找最有效的方法,而您还没有向我们展示您尝试过的方法。
  • 这真的不清楚你要做什么......预期的输出不一致,根本不符合“我想在 5 个字符后修剪”的描述。请给出具体的例子并展示你尝试过的内容
  • 您以什么指标衡量“最有效”?
  • 你试过什么代码?这实际上只是死记硬背的字符串处理。没有任何神奇的捷径。决定你想用什么算法来决定你想在哪里闯入...,然后编写代码来实现那个算法。此外,大多数像这样的修剪操作都会给自己一个最大数量的字符,它们将允许它们保持不间断,因为通常这样做的全部目的是将字符串的一些缩写表示适合预定义的空间。所以,在你的 #2 案例中,如果你根本不破坏它,它就会违背典型的目的。
  • 我仍然不清楚收缩规则是什么。避免分解成部分的算法被认为是“一个词”?如果你在一个词内停下来会发生什么——你是展示整个事情还是隐藏它?这取决于职位吗?如果它是名称中的第一个单词,似乎您想显示整个单词,但如果它是第二个单词,则隐藏它。但是如果是第三个呢? my.w.another_word?另外,您是要实际 文件扩展名检查还是只需要足够接近(.tar.gz 被视为.tar

标签: javascript string file ecmascript-6


【解决方案1】:

如果我们把点字符.当作文件扩展名的分隔符,那么你的要求可以用一行JavaScript来解决:

name.replace(new RegExp('(^[^\\.]{' + chars + '})[^\\.]+'), '$1' + subst);

演示代码在以下sn-p中:

function f(name, chars, subst) {
  return name.replace(
    new RegExp('(^[^\\.]{' + chars + '})[^\\.]+'), '$1' + subst);
}


test('myAwesomeFile.min.css', 5, '...', 'myAwe....min.css');
test('my Awesome File.tar.gz', 5, '...', 'my Aw....tar.gz');
test('file.png', 5, '...', 'file.png');

function test(filename, length, subst, expected) {
  let actual = f(filename, length, subst);
  console.log(actual, actual === expected ? 'OK' : 'expected: ' + expected);
}

在 Windows 上,AFAIK,文件扩展名只是最后一个点之后的内容。因此,从技术上讲,"myAwesomeFile.min.css" 的文件扩展名就是css"my Awesome File.tar.gz" 的文件扩展名就是gz

在这种情况下,你的要求仍然可以用一行 JavaScript 解决:

name.replace(new RegExp('(^.{' + chars + '}).+(\\.[^\\.]*$)'), '$1' + subst + '$2');

演示代码在以下sn-p中:

function f(name, chars, subst) {
  return name.replace(
    new RegExp('(^.{' + chars + '}).+(\\.[^\\.]*$)'), '$1' + subst + '$2');
}


test('myAwesomeFile.min.css', 5, '...', 'myAwe....css');
test('my Awesome File.tar.gz', 5, '...', 'my Aw....gz');
test('file.png', 5, '...', 'file.png');

function test(filename, length, subst, expected) {
  let actual = f(filename, length, subst);
  console.log(actual, actual === expected ? 'OK' : 'expected: ' + expected);
}

如果您真的想允许具有特定多个扩展的边缘情况,您可能需要定义所有允许的多个扩展的综合列表,以了解如何处理"my.awesome.file.min.css" 之类的情况。在确定任何解决方案的效率之前,您需要提供您想要包含的所有案例的列表。

【讨论】:

    【解决方案2】:

    很难解释所有扩展(包括边缘情况)。有关常见扩展名的示例,请参阅此列表:https://www.computerhope.com/issues/ch001789.htm。具有这么多扩展的事件,列表是所有扩展的详尽列表。

    你的函数没问题,但考虑到更多的情况,它可以重写为:

    function trimFileName(filename, limit = 5, spacer = '.') {
      const split = filename.indexOf(".");
      const name = filename.substring(0, split);
      const ext = filename.substring(split);
    
      let trimName = name.substring(0, limit);
    
      if (name.length > trimName.length)
        trimName = trimName.padEnd(limit + 3, spacer);
    
      return trimName + ext;
    }
    
    console.log(trimFileName("myAwesomeFile.min.css"));
    console.log(trimFileName("my Awesome File.tar.gz"));
    console.log(trimFileName("file.png"));

    【讨论】:

      【解决方案3】:

      以下是一种非常简单的方法,可以按照您想要的方式实现缩短。代码中有注释,但如果有什么需要补充说明的,请告诉我:

      //A simple object to hold some configs about how we want to shorten the file names
      const config = {
        charsBeforeTrim: 5,
        seperator: '.',
        replacementText: '....'
      };
      
      //Given file names to shorten
      const files = ['myAwesomeFile.min.css', 'my Awesome File.tar.gz', 'file.png'];
      
      //Function to do the actual file name shortening
      const shorten = s =>
        s.length > config.charsBeforeTrim ? `${s.substring(0, config.charsBeforeTrim)}${config.replacementText}` : s;
      
      //Function to generate a short file name with extension(s)
      const generateShortName = (file, config) => {
        //ES6 Array destructuring makes it easy to get the file name in a unique variable while keeping the remaining elements (the extensions) in their own array:
        const [name, ...extensions] = file.split(config.seperator);
      
        //Simply append all remaining extension chunks to the shortName
        return extensions.reduce((accum, extension) => {
          accum += `${config.seperator}${extension}`;
          return accum;
        }, shorten(name));
      };
      
      //Demonstrate usage
      const shortFileNames = files.map(file => generateShortName(file, config));
      
      console.log(shortFileNames);

      【讨论】:

        【解决方案4】:

        const parse = (filename, extIdx = filename.lastIndexOf('.')) => ({
          name: filename.substring(0, extIdx),
          extension: filename.substring(extIdx + 1),
        })
        
        const trimFileName = (
          filename, size = 5, fill = '...', 
          file = parse(filename),
          head = file.name.substring(0, size)
        ) => file.name.length >= size ? `${head}${fill}${file.extension}` : filename
        
        /* - - - - - - - - - - - - - - - - - - - - - - - - - */
        
        ;[
          'myAwesomeFile.min.css', 
          'my.Awesome.File.min.css',
          'my Awesome File.tar.gz',
          'file.png',
        ].forEach(f => console.log(trimFileName(f)))

        【讨论】:

        • 如果文件名包含“.”怎么办。假设文件名是myAwesome.File.css
        • 那么'File.css'就是扩展名。确实没有很好的方法来防止错误的文件名。例如,“this.is.filename.not.extension.txt”是一个有效的 txt 文件。我想我应该只考虑最后一个点作为扩展分隔符。
        【解决方案5】:

        您可以相当直接地提取您的扩展条件(很容易替换为有效扩展名列表),然后正则表达式提取最后一部分。然后你只需对文件名添加一个检查(从文件名的开头开始)来修剪结果。

          const trim = (string, x) => {
              // We assume that up to last two . delimited substrings of length are the extension
              const extensionRegex = /(?:(\.[a-zA-Z0-9]+){0,2})$/g;
              const { index } = extensionRegex.exec(string);
              // No point in trimming since result string would be longer than input
              if (index + 2 < x) {
                return string;
              }
              return string.substr(0, x) + ".." + string.substr(index);
            };
        
          /* Assert that we keep the extension */
          console.log("cat.tar.gz", trim("cat.tar.gz", 100) == "cat.tar.gz");
          console.log("cat.zip", trim("cat.zip", 100) == "cat.zip");
          /* Assert that we keep x characters before trim */
          console.log("1234567890cat.tar.gz",!trim("1234567890cat.tar.gz",10).includes("cat"));
          console.log("1234567890cat.zip", !trim("1234567890cat.zip", 10).includes("cat"));

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-11-28
          • 1970-01-01
          • 2016-02-22
          • 2017-12-25
          • 1970-01-01
          • 1970-01-01
          • 2015-04-07
          相关资源
          最近更新 更多