【问题标题】:Split string at space after certain number of characters in Javascript在Javascript中一定数量的字符后在空格处拆分字符串
【发布时间】:2018-09-24 23:14:14
【问题描述】:

我正在尝试创建一个工具,该工具接受输入文本并将其拆分为具有特定字符数的文本块。但是,我需要确保它不会在单词中间拆分文本。

就我而言,我在 155 个字符后拆分字符串。

我已经进行了大量搜索以尝试找到解决方案,但我担心它可能比我对 Javascript 的了解更复杂。我相信我只需要制定某种逻辑,让拆分器回溯到要拆分的空间,如果它位于单词的中间,但我不知道如何写出这样的东西。

这是我目前的 javascript 代码:

function splitText() {
    "use strict";
    var str = document.getElementById("user_input").value;
    var size = 195;
    var chunks = new Array(Math.ceil(str.length / size)),
        nChunks = chunks.length;

    var newo = 0;
    for (var i = 0, o = 0; i < nChunks; ++i, o = newo) {
          newo += size;
          chunks[i] = str.substr(o, size);
    }

    var newq = 0;
    for (var x = 0, q = 0; x < nChunks; ++x, q = newq) {
        $("#display").append("<textarea readonly>" + chunks[x] + "</textarea><br/>");
    }
}

这是我的 HTML:

<body>
    <content>
        <h1>Text Splitter</h1>
        <form>
            <label>Enter a Message</label>
            <input type="text" name="message" id="user_input">
        </form>
        <form>
            <input type="button" onclick="splitText();" id="submit" value="Submit!"> <br/>
        </form>
        <label>Your split message: </label>
        <p><span id='display'></span></p>
    </content>
</body>

以下是当前工作形式的代码,如果您想看一下: https://jsfiddle.net/add4s7rs/7/

谢谢!感谢您的帮助!

【问题讨论】:

  • 所以,为了清楚起见,将字符串拆分为第一个新词出现在字符 155 处或之后?
  • 我想确保它不会超过 155 限制。总是在它之前的空间分割。另外,如果您想查看它的实际效果,我添加了一个 jsfiddle 链接。
  • 好的,所以最大长度为 155,但容纳最后一个完整单词的长度可能会更少?
  • 我相信这是正确的,是的!

标签: javascript html


【解决方案1】:

一种使用正则表达式将字符串拆分为一定长度的块的简单方法:

const chunks = str.match(/.{1,154}(\s|$)/g);

一些例子:

const str = 'the quick brown fox jumps over the lazy dog';

console.log(str.match(/.{1,10}(\s|$)/g))
console.log(str.match(/.{1,15}(\s|$)/g))

这是可行的,因为量词(在本例中为 {1,154})在默认情况下是贪婪的,并且会尝试匹配尽可能多的字符。将(\s|$) 放在.{1,154} 后面会强制匹配在空白字符或字符串结尾处终止。所以.{1,154}(\s|$) 将匹配最多 154 个字符,后跟一个空格字符。然后/g 修饰符使其继续匹配整个字符串。

把它放在你的函数的上下文中:

function splitText() {
    "use strict";
    var str = document.getElementById("user_input").value;
    var chunks = str.match(/.{1,154}(\s|$)/g);

    chunks.forEach(function (i,x) {
        $("#display").append("<textarea readonly>" + chunks[x] + "</textarea><br/>");
    });
}

请注意(正如 cmets 中所指出的),如果字符串中的某个单词长于块的长度,则此代码将失败。

【讨论】:

  • 这工作得很好,除了最后一个字符串它切断了最后一个单词。有没有办法解决这个问题?
  • 糟糕!现在修复了正则表达式。很抱歉 - 我应该在我的例子中注意到。
  • 啊,非常感谢!还有一个相关但不相关的问题。如果我想添加一个字符,在除最后一行之外的每一行的末尾都说一个 +,这可能吗?
  • 注意:如果单词长度超过 (154) 个字符 var str = 'the quick brown fox somersaulted over the lazy dog'; console.log(str.match(/.{1,10}(\s|$)/g)) (5) ["the quick ", "brown fox ", "mersaulted ", "over the ", "lazy dog"],这将失败
  • @CodyMoniz 你是对的——但我不知道有这么长的词。英文词典中最长的单词只有45个字母。
【解决方案2】:

你可以使用这样的简单函数:

function split(string) {
  for(i=154; i>=0; i--) {
    if(string.charAt(i) == " ") {
      var newString1 = string.slice(0, i);
      var newString2 = string.slice(i);
    }
  }
}

如果您愿意,也可以随时将它们放入数组中,而不是分配给单独的字符串。

【讨论】:

  • 您不想创建一个循环遍历字符串 154 次以计数到 155。您知道要在第 154 个字符之后操作字符串;去做就对了! ;)
  • 循环从 154 开始倒计时,直到到达一个空格。
【解决方案3】:

此解决方案的逻辑是设置最大块大小,然后在需要时减小该大小以符合您的要求。使用了一个 while 循环和一点点 C 风格的逻辑。

function splitText() {
    "use strict";

    var str = document.getElementById("user_input").value;

    // Maximum allowed chunk size
    let MAX_CHUNK_SIZE = 155;
    let chunks = new Array();
    let current_chunk_position = 0;

    while(current_chunk_position < str.length){

        let current_substring = str.substr(current_chunk_position, MAX_CHUNK_SIZE);

        let last_index = current_substring.lastIndexOf(" ") > 0 ? current_substring.lastIndexOf(" ") : MAX_CHUNK_SIZE;

        let chunk = str.substr(current_chunk_position, last_index);
        chunks.push(chunk);

        current_chunk_position += last_index;
    }

    var newq = 0;
    for (var x = 0, q = 0; x < nChunks; ++x, q = newq) {
        $("#display").append("<textarea readonly>" + chunks[x] + "</textarea><br/>");
    }
}

【讨论】:

    【解决方案4】:

    一种更简单的方法是将输入的文本拆分为单个单词的数组,然后遍历数组并重新构建字符串,并计算在数组中添加下一个单词是否会让你失望你的最大尺寸。

    另外,请注意,您应该将所有 form 元素保存在单个 form 中。

    最后,您不应使用内联 HTML 事件属性(onclick 等)。这是我们在 20 多年前使用的一种技术,在我们没有标准和最佳实践之前,不幸的是,这种技术的使用如此多产,它不会因为它应得的突然死亡而死去。 There are many reasons not to code this way 而是使用现代方法在单独的 JavaScript 中使用 .addEventListener() 进行所有事件处理。

    // Don't set variables to properties of DOM elements, set them to the element
    // itself so that if you ever want a different property value, you don't have to
    // re-scan the DOM for the same element again.
    var str = document.getElementById("user_input");
    var output = document.getElementById("display");
    
    document.getElementById("go").addEventListener("click",function(){
        "use strict";
        const size = 155; // Constant is more appropriate here
        var words = str.value.split(/\s+/g); // Create array of all words in field
        
        var finalString = "";
        
        // Loop through array
        for(var i = 0; i < words.length; i++){
          if((finalString + " " + words[i]).length <= size){
            finalString += " " + words[i];
          } else {
            break; // Max size exceeded - quit loop!
          }
        }
        
        // Update field with correct value
        output.textContent = finalString;
        console.log(finalString.length);
    });
    textarea {
      width:500px;
      height:100px;
    }
    <h1>Text Splitter</h1>
            <form>
                <label>Enter a Message
                <textarea name="message" id="user_input">This is a test of the emergency broadcast system. If this had been an actual emergency, you would have been informed as to what instructions you should follow in order to remain safe at all times.</textarea></label>
                <input type="button" id="go" value="Submit!"><br>
            </form>
            <label>Your split message: </label>
            <p><span id='display'></span></p>

    【讨论】:

    • 我认为您误解了这个问题。他需要将文本分成块,而不仅仅是剪切它并得到第一个块:-) (对不起,如果我在回答中拼错了你的名字)
    • @blex 我不知道。我在他最初的问题中问了他几个澄清问题,这就是我相信他在问的问题。我猜我们会看到的。
    • 用很长的文本试试他的 JS Fiddle,结果你会看到多个 textareas,而你的答案只输出一个 textContent
    • @blex 我做到了。它似乎在做我的代码所做的事情(除了他的计数不正确)。
    猜你喜欢
    • 2010-12-13
    • 1970-01-01
    • 2017-06-18
    • 1970-01-01
    • 1970-01-01
    • 2012-01-08
    • 1970-01-01
    • 2013-04-19
    相关资源
    最近更新 更多