按单词将字符串一分为二

14
我处于这样一种情况,想要将一个字符串分成两半,同时保证单词完整性。例如,不希望把this string here分成this str ing here,而希望分成this string here
我认为第一步可以根据空格将字符串拆分成数组,然后根据这些片段计算长度,但在我的尝试中,较长的字符串被错误地拆分了。

请展示您的尝试! - Bergi
1
@Bergi 我在弄清楚如何做之后回答了这个问题。我的初始尝试中出现的错误与在检查单词数组时未添加已删除的空格有关。我的可行答案如下。 - AlbertEngelB
7个回答

21

寻找中间位置前后的第一个空格,并选择离中间位置最近的那个。

示例:

var s = "This is a long string";

var middle = Math.floor(s.length / 2);
var before = s.lastIndexOf(' ', middle);
var after = s.indexOf(' ', middle + 1);

if (middle - before < after - middle) {
    middle = before;
} else {
    middle = after;
}

var s1 = s.substr(0, middle);
var s2 = s.substr(middle + 1);

演示:http://jsfiddle.net/7RNBu/

(此代码假定中间实际上有空格。您还应添加检查 beforeafter 是否为 -1。)

编辑:

我在节点中提到的检查将如下面正确执行:

if (before == -1 || (after != -1 && middle - before >= after - middle)) {
    middle = after;
} else {
    middle = before;
}

这里有一个工具箱,您可以编辑文本并立即查看结果:http://jsfiddle.net/Guffa/7RNBu/11/


非常好!我认为这比我的解决方案好多了。 - AlbertEngelB

3

我本想留下评论,但是我的声望值不够。目前最受欢迎的解决方案很容易失败,因为它在使用indexOf方法时没有检查“-1”。请参见这个示例:

http://jsfiddle.net/7RNBu/7/

var s = "This is a long strinjjjjjjjjjjjjjjjjg";
var middle = Math.floor(s.length / 2);
var before = s.lastIndexOf(' ', middle);
var after = s.indexOf(' ', middle + 1);

if (middle - before < after - middle) {
    middle = before;
} else {
    middle = after;
}

var s1 = s.substr(0, middle);
var s2 = s.substr(middle + 1);

这里有一些免费的声望。实际上,如果indexOf调用返回-1,这并不重要。我只能看到两种边缘情况,即字符串为空或没有空格。无论哪种方式,您都会在s1中得到字符串(""或"aaaa")。 - AlbertEngelB
谢谢您的回复,Dropped.on.Caprica。我有点困惑,如果使用indexOf时-1无关紧要,那么为什么我提供的例子会失败呢? - wusauarus
哈哈,我太蠢了(并没有像白痴一样运行你的代码)。很好发现!给我几个小时,我会有时间想出一个解决方案;这真的不应该太难。 - AlbertEngelB
干得好,完全有效!将其作为答案提交上去,我会接受它的。我想271k声望的人不介意的。:P - AlbertEngelB
刚刚发布。谢谢Dropped.On.Caprica,我肯定可以用这些声望点数 :) - wusauarus

2
let str = 'qwerty';
let half = Math.floor(str.length / 2);
str = str.slice(0, half) + ' ' + str.slice(half, str.length);

//output
'qwe rty'

1

你可能也关心换行符、制表符以及空格,因此我会使用这样的正则表达式:

var s = "this string here";
var idx = s.length / 2;


while (idx < s.length && s[idx].match(/\s/) == null)
    idx++;

var s1 = s.substring(0, idx);
var s2 = s.substring(idx);

document.getElementById("s1").innerText = s1;
document.getElementById("s2").innerText = s2;

请查看这个示例:http://jsfiddle.net/nS6Bj/5/


你的示例在jsFiddle中似乎无法处理换行符或制表符。我认为,如果您需要支持按换行符和制表符拆分,则可以修改@Guffa的答案以接受接受的分隔符参数。您需要一个特定于分隔符的变量,在最接近的前后变量上进行拆分。 - AlbertEngelB
我的评论在我脑海中更有意义。如果你需要,我可以给你举个例子,我想。 - AlbertEngelB

0
         <h1>
              <span>
                // for first half start from 0 till middle
                {title.substring(0, title.length / 2)}
              </span>
              <span>
                // second half just point the starting point
                {title.substring(title.length / 2)}
              </span>
         </h1>

0

一开始我以为是一个偏移量错误,但最终我解决了它。这里有一个可行的例子。

现在来分解所使用的逻辑:

var calculate = function(initialString) {
  var halfwayPoint = Math.floor(initialString.length / 2);
  var strArray = initialString.split(' ');
  // Caluclate halfway point, then break string into words

  var wordFlag;  // Will be split point
  var charCount = 0;
  _.each( strArray, function(word, strArrayIndex) {
    if (wordFlag) return false;
    // If we have the location, exit

    // If charCount is before the halfway point
    // and the end of word is after halfway point
    // Then set the flag
    // We add strArrayIndex to the word length to include spaces
    if (charCount <= halfwayPoint && 
      ((charCount + word.length + strArrayIndex) >= halfwayPoint) ) {
      wordFlag = strArrayIndex;
      return false;
    }

    // Increase charCount to be length at the end of this word
    charCount += (word.length);
  });

  if (!wordFlag) return null;

  // Split the word array by the flag we figured out earlier
  var lineOneArray = strArray.slice(0, (wordFlag + 1));
  var lineTwoArray = strArray.slice(wordFlag + 1);


  // We now join the word arrays into a string, stripping beginning and ending spaces.
  var stOne = (lineOneArray.join(' ')).replace(/^\s\s*/, '').replace(/\s\s*$/, '');
  var stTwo = (lineTwoArray.join(' ')).replace(/^\s\s*/, '').replace(/\s\s*$/, '');

  // Finally return the split strings as an array.
  return [stOne, stTwo];
};

如果有人发现我的逻辑有漏洞,请告诉我!虽然我相信这在大多数情况下都是有效的。

如果您希望第二个字符串比第一个字符串更长(即在中间单词之前而不是之后换行),则不要将+1添加到wordFlag。


0

这将根据单词计数拆分您的字符串(而不是字符计数,因此每半部分的确切长度可能会有很大差异,具体取决于长短单词的位置)。

var s = "This is a string of filler text";

var pieces = s.split(" "),
    firstHalfLength = Math.round(pieces.length/2),
    str1 = "",
    str2 = "";

for (var i = 0; i < firstHalfLength; i++){
    str1 += (i!=0?" ":"") + pieces[i];
}
for (var i = firstHalfLength; i < pieces.length; i++){
    str2 += (i!=firstHalfLength?" ":"") + pieces[i];
}

document.write(s);
document.write("<br />"+str1);
document.write("<br />"+str2);

// Output
This is a string of filler text
This is a string
of filler text

http://jsfiddle.net/daCrosby/7RNBu/2/


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