将java中的字符串拆分为等长子字符串,同时保持单词边界

将java中的字符串拆分为等长子字符串,同时保持单词边界,java,string,Java,String,如何在保持单词边界的同时将字符串拆分为最大字符长度的相等部分 比如说,如果我想将一个字符串“hello world”拆分为最多7个字符的相等子字符串,它应该返回我 "hello " 及 但是我当前的实现返回了 "hello w" 及 我使用下面的代码将输入字符串分成相等的部分 public static List<String> splitEqually(String text, int size) { // Give the list the right capacit

如何在保持单词边界的同时将字符串拆分为最大字符长度的相等部分

比如说,如果我想将一个字符串“hello world”拆分为最多7个字符的相等子字符串,它应该返回我

"hello "

但是我当前的实现返回了

"hello w"

我使用下面的代码将输入字符串分成相等的部分

public static List<String> splitEqually(String text, int size) {
    // Give the list the right capacity to start with. You could use an array
    // instead if you wanted.
    List<String> ret = new ArrayList<String>((text.length() + size - 1) / size);

    for (int start = 0; start < text.length(); start += size) {
        ret.add(text.substring(start, Math.min(text.length(), start + size)));
    }
    return ret;
}
公共静态列表(字符串文本,整数大小){
//首先为列表提供正确的容量。可以使用数组
//如果你愿意的话。
List ret=新的数组列表((text.length()+size-1)/size);
对于(int start=0;start
在将字符串拆分为子字符串时是否可以保持单词边界


更具体地说,我需要字符串拆分算法考虑空格提供的单词边界,而不是在拆分字符串时仅依赖字符长度,虽然这也需要考虑,但更像是最大字符范围,而不是硬编码的字符长度。

如果我理解您的如果问题正确,则此代码应该执行您需要的操作(但它假定
maxLenght
等于或大于最长单词)

输出:

Hello
there, my
name is
not
importnant
right now.
I am just
simple
sentecne
used to
test few
things.
“\\G\\s*(.{1,“+maxLenght+”})(?=\\s |$)”
regex的简短(或非简短)解释:

(让我们记住,在Java中,
\
不仅在正则表达式中是特殊的,而且在字符串文本中也是特殊的,因此要使用预定义的字符集,如
\d
,我们需要将其写成
“\\d”
,因为我们还需要在字符串文本中转义该
\

  • \G
    -锚定表示以前建立的匹配的结束,或者如果还没有匹配(当我们刚开始搜索时)字符串的开始(与
    ^
    相同)
  • \s*
    -表示零个或多个空格(
    \s
    表示空格,
    *
    “零个或多个”量词)
  • (.{1,“+maxLenght+”})
    -让我们把它分成更多的部分(在运行时
    :maxLenght
    将保存一些类似于10的数值,因此正则表达式将它视为
    {1,10}
    • 表示任何字符(实际上,默认情况下,它可以表示除行分隔符以外的任何字符,如
      \n
      \r
      ,但由于
      模式。DOTALL
      标志,它现在可以表示任何字符-,如果要开始单独拆分每个句子,则可以取消此方法参数,因为它的开头将以新行打印。)无论如何
    • {1,10}
      -这是一个量词,允许前面描述的元素出现1到10次(默认情况下,将尝试查找匹配重复的最大数量)
    • {1,10}
      -根据我们刚才所说的,它只表示“任何字符中的1到10个”
    • -创建括号,这种结构允许我们保存匹配的特定部分(这里我们在
      \\s*
      之后添加括号,因为我们只希望使用空格后面的部分)
  • (?=\\s |$)
    -是一种机制,可确保与
    {1,10}
    匹配的文本后面有:

    • 空格(
      \\s

      或(写为
      |

    • 字符串后面的
      $
      结尾


所以多亏了
{1,10}
,我们最多可以匹配10个字符。但是在
(?=\\s |$)
之后,我们要求由
{1,10}
匹配的最后一个字符不是未完成单词的一部分(后面必须有空格或字符串结尾)。

非正则表达式解决方案,以防有人感到更舒服(?)不使用正则表达式:

private String justify(String s, int limit) {
    StringBuilder justifiedText = new StringBuilder();
    StringBuilder justifiedLine = new StringBuilder();
    String[] words = s.split(" ");
    for (int i = 0; i < words.length; i++) {
        justifiedLine.append(words[i]).append(" ");
        if (i+1 == words.length || justifiedLine.length() + words[i+1].length() > limit) {
            justifiedLine.deleteCharAt(justifiedLine.length() - 1);
            justifiedText.append(justifiedLine.toString()).append(System.lineSeparator());
            justifiedLine = new StringBuilder();
        }
    }
    return justifiedText.toString();
}
输出:

Long sentence
with spaces,
and punctuation
too. And
supercalifragilisticexpialidocious
words. No
carriage
returns, tho --
since it would
seem weird to
count the words
in a new line
as part of the
previous
paragraph's
length.
它会考虑长度超过设置限制的单词,因此不会跳过它们(与regex版本不同,regex版本在找到supercalifragilisticexpialidosus时会停止处理)


PS:在我提出这个解决方案后,我提出了关于所有输入字都应该短于设定限制的意见;)

你能用更多的字再添加一个输入/输出示例吗?当然可以,e.x.“需要速度热追踪”,最大字符范围指定为16。。。我需要根据单词边界分割字符串,因此输出应该是“速度需要”和“热追踪”,但目前我得到的实现是“速度需要h”和“ot追踪”,所以规则是在最大字符范围或之前的空白处分割?如果第一个单词比字符范围长怎么办?你中间劈开了吗?示例:“reallylongwordisfirst和此处有几个常规单词”,长度为7。您是否希望“reallylongwordisfirst”和“此处”有几个“常规”单词?我的最大长度为4000个字符。。我想知道是否有一个4000个字符的单词,但无论如何,这是为android文本到语音引擎设计的,如果不考虑单词边界,它会弄乱单词的发音,另一方面,它也有一个一次可以接受的最大字符范围。。。所以我希望现在你能看到我的难题,你允许分裂的话超过你的限制?例如,如果将最大字符数设置为
7
how
“hohohohoho圣诞快乐
应该拆分吗?将很快包括此正则表达式的解释,现在请测试它是否符合您的要求,并让我知道它是否有效。谢谢您,它工作得很好…只需再问一个问题,我已经能够将单个字符串组放入列表中。但是有没有办法指定arralist的大小。。我听到它更快的时候,ar
Hello
there, my
name is
not
importnant
right now.
I am just
simple
sentecne
used to
test few
things.
private String justify(String s, int limit) {
    StringBuilder justifiedText = new StringBuilder();
    StringBuilder justifiedLine = new StringBuilder();
    String[] words = s.split(" ");
    for (int i = 0; i < words.length; i++) {
        justifiedLine.append(words[i]).append(" ");
        if (i+1 == words.length || justifiedLine.length() + words[i+1].length() > limit) {
            justifiedLine.deleteCharAt(justifiedLine.length() - 1);
            justifiedText.append(justifiedLine.toString()).append(System.lineSeparator());
            justifiedLine = new StringBuilder();
        }
    }
    return justifiedText.toString();
}
String text = "Long sentence with spaces, and punctuation too. And supercalifragilisticexpialidocious words. No carriage returns, tho -- since it would seem weird to count the words in a new line as part of the previous paragraph's length.";
System.out.println(justify(text, 15));
Long sentence
with spaces,
and punctuation
too. And
supercalifragilisticexpialidocious
words. No
carriage
returns, tho --
since it would
seem weird to
count the words
in a new line
as part of the
previous
paragraph's
length.