天道酬勤,学无止境

在自然语言中断处拆分字符串(Split String at natural language breaks)

问题

概述

我将字符串发送到接受最大长度为 300 个字符的文本到语音转换服务器。 由于网络延迟,返回的每个语音部分之间可能存在延迟,因此我想尽可能在​​最“自然的停顿”处分解语音。

每个服务器请求都会花费我的钱,所以理想情况下我会发送最长的字符串,最多允许的最大字符数。

这是我目前的实现:

private static final boolean DEBUG = true;

private static final int MAX_UTTERANCE_LENGTH = 298;
private static final int MIN_UTTERANCE_LENGTH = 200;

private static final String FULL_STOP_SPACE = ". ";
private static final String QUESTION_MARK_SPACE = "? ";
private static final String EXCLAMATION_MARK_SPACE = "! ";
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
private static final String COMMA_SPACE = ", ";
private static final String JUST_A_SPACE = " ";

public static ArrayList<String> splitUtteranceNaturalBreaks(String utterance) {

    final long then = System.nanoTime();

    final ArrayList<String> speakableUtterances = new ArrayList<String>();

    int splitLocation = 0;
    String success = null;

    while (utterance.length() > MAX_UTTERANCE_LENGTH) {

        splitLocation = utterance.lastIndexOf(FULL_STOP_SPACE, MAX_UTTERANCE_LENGTH);

        if (DEBUG) {
            System.out.println("(0 FULL STOP) - last index at: " + splitLocation);
        }

        if (splitLocation < MIN_UTTERANCE_LENGTH) {
            if (DEBUG) {
                System.out.println("(1 FULL STOP) - NOT_OK");
            }

            splitLocation = utterance.lastIndexOf(QUESTION_MARK_SPACE, MAX_UTTERANCE_LENGTH);

            if (DEBUG) {
                System.out.println("(1 QUESTION MARK) - last index at: " + splitLocation);
            }

            if (splitLocation < MIN_UTTERANCE_LENGTH) {
                if (DEBUG) {
                    System.out.println("(2 QUESTION MARK) - NOT_OK");
                }

                splitLocation = utterance.lastIndexOf(EXCLAMATION_MARK_SPACE, MAX_UTTERANCE_LENGTH);

                if (DEBUG) {
                    System.out.println("(2 EXCLAMATION MARK) - last index at: " + splitLocation);
                }

                if (splitLocation < MIN_UTTERANCE_LENGTH) {
                    if (DEBUG) {
                        System.out.println("(3 EXCLAMATION MARK) - NOT_OK");
                    }

                    splitLocation = utterance.lastIndexOf(LINE_SEPARATOR, MAX_UTTERANCE_LENGTH);

                    if (DEBUG) {
                        System.out.println("(3 SEPARATOR) - last index at: " + splitLocation);
                    }

                    if (splitLocation < MIN_UTTERANCE_LENGTH) {
                        if (DEBUG) {
                            System.out.println("(4 SEPARATOR) - NOT_OK");
                        }

                        splitLocation = utterance.lastIndexOf(COMMA_SPACE, MAX_UTTERANCE_LENGTH);

                        if (DEBUG) {
                            System.out.println("(4 COMMA) - last index at: " + splitLocation);
                        }

                        if (splitLocation < MIN_UTTERANCE_LENGTH) {
                            if (DEBUG) {
                                System.out.println("(5 COMMA) - NOT_OK");
                            }

                            splitLocation = utterance.lastIndexOf(JUST_A_SPACE, MAX_UTTERANCE_LENGTH);

                            if (DEBUG) {
                                System.out.println("(5 SPACE) - last index at: " + splitLocation);
                            }

                            if (splitLocation < MIN_UTTERANCE_LENGTH) {
                                if (DEBUG) {
                                    System.out.println("(6 SPACE) - NOT_OK");
                                }

                                splitLocation = MAX_UTTERANCE_LENGTH;

                                if (DEBUG) {
                                    System.out.println("(6 MAX_UTTERANCE_LENGTH) - last index at: " + splitLocation);
                                }

                            } else {
                                if (DEBUG) {
                                    System.out.println("Accepted");
                                }

                                splitLocation -= 1;
                            }
                        }
                    } else {
                        if (DEBUG) {
                            System.out.println("Accepted");
                        }

                        splitLocation -= 1;
                    }
                } else {
                    if (DEBUG) {
                        System.out.println("Accepted");
                    }
                }
            } else {
                if (DEBUG) {
                    System.out.println("Accepted");
                }
            }
        } else {
            if (DEBUG) {
                System.out.println("Accepted");
            }
        }

        success = utterance.substring(0, (splitLocation + 2));

        speakableUtterances.add(success.trim());

        if (DEBUG) {
            System.out.println("Split - Length: " + success.length() + " -:- " + success);
            System.out.println("------------------------------");
        }

        utterance = utterance.substring((splitLocation + 2)).trim();
    }

    speakableUtterances.add(utterance);

    if (DEBUG) {

        System.out.println("Split - Length: " + utterance.length() + " -:- " + utterance);

        final long now = System.nanoTime();
        final long elapsed = now - then;

        System.out.println("ELAPSED: " + TimeUnit.MILLISECONDS.convert(elapsed, TimeUnit.NANOSECONDS));

    }

    return speakableUtterances;
}

由于无法在lastIndexOf使用正则表达式,因此很难看。 抛开丑陋不谈,它实际上相当快。

问题

理想情况下,我想使用正则表达式来匹配我的首选分隔符之一:

private static final String firstChoice = "[.!?" + LINE_SEPARATOR + "]\\s+";
private static final Pattern pFirstChoice = Pattern.compile(firstChoice);

然后使用匹配器来解析位置:

    Matcher matcher = pFirstChoice.matcher(input);

    if (matcher.find()) {
        splitLocation = matcher.start();
    }

我当前实现中的替代方法是存储每个分隔符的位置,然后选择最接近MAX_UTTERANCE_LENGTH

我尝试了各种方法将MIN_UTTERANCE_LENGTHMAX_UTTERANCE_LENGTH应用于模式,因此它只在这些值之间捕获并使用环视来反向迭代?<= ,但这就是我的知识开始让我失望的地方:

private static final String poorEffort = "([.!?]{200, 298})\\s+");

最后

我想知道你们中的任何一个正则表达式大师是否可以实现我所追求的并确认实际上它是否会更有效?

我提前谢谢你。

参考:

  • 在自然中断处拆分字符串(Python)
  • 环视
  • 使用最小大小和分隔符拆分令牌的正则表达式
回答1

我会做这样的事情:

Pattern p = Pattern.compile(".{1,299}(?:[.!?]\\s+|\\n|$)", Pattern.DOTALL);
Matcher matcher = p.matcher(text);
while (matcher.find()) {
    speakableUtterances.add(matcher.group().trim());
}

正则表达式的解释:

.{1,299}                 any character between 1 and 299 times (matching the most amount possible)
(?:[.!?]\\s+|\\n|$)      followed by either .!? and whitespaces, a newline or the end of the string

您可以考虑将标点符号扩展为\p{Punct} ,请参阅模式的 javadoc。

您可以在 ideone 上查看工作示例。

回答2

Unicode 标准定义了如何将文本分解为句子和其他逻辑组件。 这是一些工作伪代码:

// tests two consecutive codepoints within the text to detect the end of sentences
boolean continueSentence(Text text, Range range1, Range range2) {
    Code code1 = text.code(range1), code2 = text.code(range2);

    // 0.2  sot ÷   
    if (code1.isStartOfText())
        return false;

    // 0.3      ÷    eot
    if (code2.isEndOfText())
        return false;

    // 3.0  CR  ×    LF
    if (code1.isCR() && code2.isLF())
        return true;

    // 4.0  (Sep | CR | LF) ÷   
    if (code1.isSep() || code1.isCR() || code1.isLF())
        return false;

    // 5.0      ×    [Format Extend]
    if (code2.isFormat() || code2.isExtend())
        return true;

    // 6.0  ATerm   ×    Numeric
    if (code1.isATerm() && (code2.isDigit() || code2.isDecimal() || code2.isNumeric()))
        return true;

    // 7.0  Upper ATerm ×    Upper
    if (code2.isUppercase() && code1.isATerm()) {
        Range range = text.previousCode(range1);
        if (range.isValid() && text.code(range).isUppercase())
            return true;
    }

    boolean allow_STerm = true, return_value = true;

    // 8.0  ATerm Close* Sp*    ×    [^ OLetter Upper Lower Sep CR LF STerm ATerm]* Lower
    Range range = range2;
    Code code = code2;
    while (!code.isOLetter() && !code.isUppercase() && !code.isLowercase() && !code.isSep() && !code.isCR() && !code.isLF() && !code.isSTerm() && !code.isATerm()) {
        if (!(range = text.nextCode(range)).isValid())
            break;
        code = text.code(range);
    }
    range = range1;
    if (code.isLowercase()) {
        code = code1;
        allow_STerm = true;
        goto Sp_Close_ATerm;
    }
    code = code1;

    // 8.1  (STerm | ATerm) Close* Sp*  ×    (SContinue | STerm | ATerm)
    if (code2.isSContinue() || code2.isSTerm() || code2.isATerm())
        goto Sp_Close_ATerm;

    // 9.0  ( STerm | ATerm ) Close*    ×    ( Close | Sp | Sep | CR | LF )
    if (code2.isClose())
        goto Close_ATerm;

    // 10.0 ( STerm | ATerm ) Close* Sp*    ×    ( Sp | Sep | CR | LF )
    if (code2.isSp() || code2.isSep() || code2.isCR() || code2.isLF())
        goto Sp_Close_ATerm;

    // 11.0 ( STerm | ATerm ) Close* Sp* (Sep | CR | LF)?   ÷   
    return_value = false;

    // allow Sep, CR, or LF zero or one times
    for (int iteration = 1; iteration != 0; iteration--) {
        if (!code.isSep() && !code.isCR() && !code.isLF()) goto Sp_Close_ATerm;
        if (!(range = text.previousCode(range)).isValid()) goto Sp_Close_ATerm;
        code = text.code(range);
    }

Sp_Close_ATerm:
    // allow zero or more Sp
    while (code.isSp() && (range = text.previousCode(range)).isValid())
        code = text.code(range);

Close_ATerm:
    // allow zero or more Close
    while (code.isClose() && (range = text.previousCode(range)).isValid())
        code = text.code(range);

    // require STerm or ATerm
    if (code.isATerm() || (allow_STerm && code.isSTerm()))
        return return_value;

    // 12.0     ×    Any
    return true;
}

然后你可以像这样迭代句子:

// pass in a range of (0, 0) to get the range of the first sentence
// returns a range with a length of 0 if there are no more sentences
Range nextSentence(Text text, Range range) {
try_again:
    range = text.nextCode(new Range(range.start + range.length, 0));
    if (!range.isValid())
        return range;
    Range next = text.nextCode(range);
    long start = range.start;
    while (next.isValid()) && text.continueSentence(range, next))
        next = text.nextCode(range = next);
    range = new Range(start, range.start + range.length - start);

    Range range2 = text.trimRange(range);
    if (!range2.isValid())
        goto try_again;

    return range2;
}

在哪里:

  • 范围定义为从 >= start 和 < start + length 开始的范围
  • text.trimRange 删除空白字符(可选)
  • 所有的 Code.is[Type] 函数都是在 Unicode 字符数据库中查找。 例如,您会在其中一些文件中看到一些代码点被定义为“CR”、“Sep”、“StartOfText”等。
  • Text.code(range) 在 range.start 处对文本中的代码点进行解码。 不使用长度。
  • Text.nextCode 和 Text.previousCode 根据当前代码点的范围返回字符串中下一个或上一个代码点的范围。 如果该方向没有代码点,则返回无效范围,即长度为 0 的范围。

该标准还定义了迭代单词、行和字符的方法。

标签

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 解析单个句子的正则表达式是什么?(What is a regular expression for parsing out individual sentences?)
    问题 我正在寻找一个好的.NET正则表达式,可用于从文本正文中解析出单个句子。 它应该能够将以下文本块解析为正好六个句子: Hello world! How are you? I am fine. This is a difficult sentence because I use I.D. Newlines should also be accepted. Numbers should not cause sentence breaks, like 1.23. 事实证明,这比我最初想象的要更具挑战性。 任何帮助将不胜感激。 我将使用它在已知的正文上训练系统。 回答1 试试这个@"(\S.+?[.!?])(?=\s+|$)" : string str=@"Hello world! How are you? I am fine. This is a difficult sentence because I use I.D. Newlines should also be accepted. Numbers should not cause sentence breaks, like 1.23."; Regex rx = new Regex(@"(\S.+?[.!?])(?=\s+|$)"); foreach (Match match in rx.Matches(str)) { int
  • 最佳自动换行算法? [关闭](Best word wrap algorithm? [closed])
    问题 关门了。 这个问题是基于意见的。 它当前不接受答案。 想要改善这个问题吗? 更新问题,以便可以通过编辑此帖子以事实和引用的形式回答。 1年前关闭。 改善这个问题 自动换行是现代文本编辑器中的必备功能之一。 如何处理自动换行? 换行的最佳算法是什么? 如果文本是几百万行,那么我该如何快速自动换行呢? 为什么需要解决方案? 因为我的项目必须绘制具有各种缩放级别并同时具有美观外观的文本。 运行环境是Windows Mobile设备。 很小的内存大小,最高600 MHz速度。 我应该如何处理线路信息? 假设原始数据有三行。 THIS IS LINE 1. THIS IS LINE 2. THIS IS LINE 3. 之后,中断文本将如下所示: THIS IS LINE 1. THIS IS LINE 2. THIS IS LINE 3. 我应该再分配三行吗? 或其他建议? 回答1 这是我用C#编写的自动换行算法。 翻译成其他语言应该很容易(也许IndexOfAny除外)。 static char[] splitChars = new char[] { ' ', '-', '\t' }; private static string WordWrap(string str, int width) { string[] words = Explode(str, splitChars)
  • 解析自然语言(parse natural language)
    问题 开始:我知道这个系统会有缺陷! 注意:我添加了一些其他语言,因为我没有发现这个问题特定于 php..JavaScript 或 jquery 解决方案可以工作......我可以更改语言......这是我所追求的方法! 什么:我正在尝试解析一个字符串以确定用户需要什么。 这个想法是字符串是由语音生成的 示例 1:打开厨房的灯,关掉卧室和客厅的灯。 示例 2:打开厨房灯,打开卧室灯,关闭客厅灯。 示例 3:关闭我的厨房、卧室和客厅的灯。 这是一个过于简化的示例,但请注意,我想扩展到这三个房间之外,并且只控制灯光示例:外面的吊扇开... 如何:我目前正在使用一些 while 循环来遍历数组并检查某些字符串是否在数组中。 更多方法:我的想法是首先在“和”上的字符串上拆分。 然后我检查每个阵列是否打开或关闭。 如果它没有打开或关闭,我将与下一个加入阵列。 帮助:我很想清理这个概念,也很想看看别人的想法......我愿意做任何事情...... 谢谢 JT 代码: $input = 'kitchen lights on and bed and living lights off'; $output = preg_split( "/ (and) /", $input ); $num = (int)count($output); $i=0; while($i<$num){ if ((strpos
  • 如何截断PHP中最接近一定数量字符的单词的字符串?(How to Truncate a string in PHP to the word closest to a certain number of characters?)
    问题 我有一个用PHP编写的代码片段,可从数据库中提取文本块并将其发送到网页上的小部件。 原始文本块可以是一篇冗长的文章或一两个简短的句子; 但是对于此小部件,我最多只能显示200个字符。 我可以使用substr()以200个字符的形式截断文本,但是结果是在中间截断-我真正想要的是在200个字符之前的最后一个的末尾截断文本。 回答1 通过使用自动换行功能。 它将文本分成多行,以使最大宽度是您指定的宽度,并在单词边界处断开。 拆分后,您只需走第一行: substr($string, 0, strpos(wordwrap($string, $your_desired_width), "\n")); 文本本身短于所需宽度时,oneliner无法处理的一件事。 要处理这种情况,应执行以下操作: if (strlen($string) > $your_desired_width) { $string = wordwrap($string, $your_desired_width); $string = substr($string, 0, strpos($string, "\n")); } 如果文本在实际剪切点之前包含换行符,则上述解决方案存在过早剪切文本的问题。 这里是解决此问题的版本: function tokenTruncate($string, $your_desired_width
  • 我如何分割字符串,在特定字符处断开?(How do I split a string, breaking at a particular character?)
    问题 我有这串 'john smith~123 Street~Apt 4~New York~NY~12345' 使用JavaScript,将其解析为最快的方法是 var name = "john smith"; var street= "123 Street"; //etc... 回答1 使用JavaScript的String.prototype.split函数: var input = 'john smith~123 Street~Apt 4~New York~NY~12345'; var fields = input.split('~'); var name = fields[0]; var street = fields[1]; // etc. 回答2 根据ECMAScript6 ES6 ,干净的方法是解构数组: const input = 'john smith~123 Street~Apt 4~New York~NY~12345'; const [name, street, unit, city, state, zip] = input.split('~'); console.log(name); // john smith console.log(street); // 123 Street console.log(unit); // Apt 4 console.log
  • 人字或数字混合字符串的人性化或自然数排序(Humanized or natural number sorting of mixed word-and-number strings)
    问题 紧接着Sivaram Chintalapudi提出的这个问题,我对在PostgreSQL中对包含多位数字和单词/字母的混合字符串进行自然(或“人性化”)排序“是否可行”感兴趣,没有固定的解决方案。字符串中的单词和数字的模式,并且字符串中可能有多个多位数字。 我唯一看到的常规操作是在Mac OS的Finder中,它对包含混合数字和单词的文件名进行自然排序,将“ 20”放在“ 3”之后,而不是在它之前。 所需的排序规则顺序将由一种算法产生,该算法将每个字符串在字母数字边界处分成多个块,然后对每个部分进行排序,将具有常规排序规则的字母块和数字块视为整数以便进行排序。 所以: 'AAA2fred'将变为('AAA',2,'fred')并且'AAA10bob'将变为('AAA',10,'bob') 。 然后可以根据需要对它们进行排序: regress=# WITH dat AS ( VALUES ('AAA',2,'fred'), ('AAA',10,'bob') ) regress-# SELECT dat FROM dat ORDER BY dat; dat -------------- (AAA,2,fred) (AAA,10,bob) (2 rows) 与通常的字符串排序规则相比: regress=# WITH dat AS ( VALUES ('AAA2fred'), (
  • C将char数组拆分为不同的变量(C split a char array into different variables)
    问题 在C语言中,如何用定界符分隔char数组? 还是操纵字符串更好? 什么是一些不错的C字符操纵函数? 回答1 #include<string.h> #include<stdio.h> int main() { char input[16] = "abc,d"; char *p; p = strtok(input, ","); if(p) { printf("%s\n", p); } p = strtok(NULL, ","); if(p) printf("%s\n", p); return 0; } 您可以看一下这个程序。首先,您应该使用strtok(input,“,”)。input是您要分割的字符串。然后您使用strtok(NULL,“,”)。 如果返回值为true,则可以打印另一个组。 回答2 查看strtok()。 strtok()不是可重入函数。 strtok_r()是strtok()的可重入版本。 这是手册中的示例程序: #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char *argv[]) { char *str1, *str2, *token, *subtoken; char *saveptr1, *saveptr2; int j; if (argc
  • PHP REGEX-文本在换行符处由preg_split排列(PHP REGEX - text to array by preg_split at line break)
    问题 编辑: 在拆分数组上需要帮助 数组示例: array ( [0] => :some normal text :some long text here, and so on... sometimes i'm breaking down and... :some normal text :some normal text ) 好的,现在通过使用 preg_split( '#\n(?!s)#' , $text ); 我明白了 [0] => Array ( [0] => some normal text [1] => some long text here, and so on... sometimes [2] => some normal text [3] => some normal text ) 我想要这个: [0] => Array ( [0] => some normal text [1] => some long text here, and so on... sometimes i'm breaking down and... [2] => some normal text [3] => some normal text ) 正则表达式可以得到整条线,也可以在换行时拆分! 回答1 这是一个有效的示例,即使您在字符串中嵌入了冒号(但不在行首)也是如此: $input =
  • 如何在不使用strtok的情况下在C中拆分字符串(How to split string in C without using strtok)
    问题 #include <stdio.h> int main() { char string[] = "my name is geany"; int length = sizeof(string)/sizeof(char); printf("%i", length); int i; for ( i = 0; i<length; i++ ) { } return 0; } 如果我想分开打印“我的”,“名字”,“是”和“ geany”,那我该怎么办。 我当时正在考虑使用除霜器,但我不知道如何在C语言中使用它 回答1 从指向字符串开头的指针开始逐个字符地迭代,查找您的定界符每次找到一个字符串时,您都会从长度的最后一个位置得到一个字符串,该字符串的长度有所不同-为此,您可以做将新的起始位置设置为定界符+ 1,然后转到步骤2。 在字符串中剩余字符的同时执行所有这些操作... 回答2 我之所以需要这样做,是因为该环境在一个受限制的库中缺少strtok 。 这是我分割连字符分隔的字符串的方法: b = grub_strchr(a,'-'); if (!b) <handle error> else *b++ = 0; c = grub_strchr(b,'-'); if (!c) <handle error> else *c++ = 0; 此处, a以复合字符串"ABC"开头,在代码执行之后
  • 如何在 Dart 中反转字符串?(How do I reverse a String in Dart?)
    问题 我有一个字符串,我想反转它。 例如,我正在编写一个反转字符串的 AngularDart 过滤器。 这仅用于演示目的,但它让我想知道如何反转字符串。 例子: Hello, world 应该变成: dlrow ,olleH 我还应该考虑带有 Unicode 字符的字符串。 例如: 'Ame\u{301}lie' 什么是反转字符串的简单方法,即使它有? 回答1 这个问题没有很好的定义。 反转任意字符串没有意义,会导致输出中断。 第一个(可克服的)障碍是 Utf-16。 Dart 字符串被编码为 Utf-16 并且只反转代码单元会导致无效的字符串: var input = "Music \u{1d11e} for the win"; // Music 𝄞 for the win print(input.split('').reversed.join()); // niw eht rof split函数明确警告了这个问题(举个例子): 使用空字符串模式 ('') 拆分会在 UTF-16 代码单元边界而不是符文边界处拆分[.] 对此有一个简单的解决方法:不是反转单个代码单元,而是反转符文: var input = "Music \u{1d11e} for the win"; // Music 𝄞 for the win print(new String.fromCharCodes
  • 如何在批处理文件中不带for循环的情况下拆分字符串(How to split string without for loop in batch file)
    问题 我想将字符串分为两部分,而不使用任何for循环。 例如,我将字符串包含在变量中: str=45:abc 我想在一个变量中获取45 ,在另一个变量中获取abc 。 可以在批处理文件中吗? 模式就像somenumber:somestring 回答1 您可以用不同的方式拆分str。 for循环,您不想使用它。 后面的部分很容易使用* (匹配任何内容,直到...) set "var2=%str:*:=%" 引导部分可以用一个讨厌的把戏来完成set "var1=%str::="^&REM #% 需要使用脱字号来逃离&符, 因此有效的将冒号替换为"&REM # set "var1=4567"&REM #abcde 这分为两个命令 set "var1=4567" REM #abcde` 完整的代码在这里: set "str=4567:abcde" echo %str% set "var1=%str::="^&REM #% set "var2=%str:*:=%" echo var1=%var1% var2=%var2% 编辑2:更稳定的领导部分 感谢Dave使用换行符的想法。 REM技术对于带有引号和特殊字符的内容不是很稳定。 但是,使用换行技巧时,存在一个更稳定的版本,当split参数比单个字符长时,该版本也可以使用。 @echo off setlocal
  • 在第n个字符处分割字符串(Splitting a string at every n-th character)
    问题 在JavaScript中,这是我们如何在每个第3个字符处分割字符串 "foobarspam".match(/.{1,3}/g) 我试图弄清楚如何用Java做到这一点。 有指针吗? 回答1 您可以这样: String s = "1234567890"; System.out.println(java.util.Arrays.toString(s.split("(?<=\\G...)"))); 产生: [123, 456, 789, 0] 正则表达式(?<=\G...)匹配一个空字符串,该字符串的最后一个匹配项( \G )后跟三个字符( ... ),前一个字符( (?<= ) ) 回答2 Java没有提供功能非常齐全的拆分实用程序,因此Guava库提供了以下功能: Iterable<String> pieces = Splitter.fixedLength(3).split(string); 查看用于拆分器的Javadoc; 它非常强大。 回答3 import java.util.ArrayList; import java.util.List; public class Test { public static void main(String[] args) { for (String part : getParts("foobarspam", 3)) { System
  • 在 JavaScript 中拆分字符串并检测换行符(Split string in JavaScript and detect line break)
    问题 我发现了一个小函数,它从textarea中获取一个字符串,然后将其放入一个canvas元素中,并在该行太长时将文本换行。 但它不检测换行符。 这是它正在做什么以及它应该做什么: 输入: Hello This is dummy text that could be inside the text area. It will then get put into the canvas. 错误输出: Hello this is dummy text that could be inside the text area. It will then get put into the canvas. 它应该输出什么: Hello This is dummy text that could be inside the text area. It will then get put into the canvas. 这是我正在使用的功能: function wrapText(context, text, x, y, maxWidth, lineHeight) { var words = text.split(' '); var line = ''; for(var n = 0; n < words.length; n++) { var testLine = line + words[n] +
  • 需要根据元素的升序中断将列表划分为列表(Haskell)(Need to partition a list into lists based on breaks in ascending order of elements (Haskell))
    问题 说我有任何这样的清单: [4,5,6,7,1,2,3,4,5,6,1,2] 我需要一个Haskell函数,它将将此列表转换为列表列表,这些列表由原始列表的各个部分组成,这些部分按升序形成一系列。 因此结果应如下所示: [[4,5,6,7],[1,2,3,4,5,6],[1,2]] 有什么建议? 回答1 ascend :: Ord a => [a] -> [[a]] ascend xs = foldr f [] xs where f a [] = [[a]] f a xs'@(y:ys) | a < head y = (a:y):ys | otherwise = [a]:xs' 在ghci中 *Main> ascend [4,5,6,7,1,2,3,4,5,6,1,2] [[4,5,6,7],[1,2,3,4,5,6],[1,2]] 回答2 您可以通过手动递归来做到这一点,但是我想相信Haskell是一种更加进化的语言。 让我们看看是否可以开发一个使用现有递归策略的解决方案。 首先是一些预备。 {-# LANGUAGE NoMonomorphismRestriction #-} -- because who wants to write type signatures, amirite? import Data.List.Split -- from package split
  • 将字符串拆分为句子(Split string into sentences)
    问题 我已经编写了这段代码,用于拆分字符串并将其存储在字符串数组中:- String[] sSentence = sResult.split("[a-z]\\.\\s+"); 但是,我添加了[az],因为我想处理一些缩写问题。 但随后我的结果显示为:- 此外,当埃弗里特(Everett)试图教他们基础数学时,他们被证明是毫无反应的 我看到我丢失了split函数中指定的模式。 对我来说,不要错过句号,但是失去单词的最后一个字母会打乱它的含义。 有人可以帮助我吗?此外,有人可以帮助我解决缩写吗? 例如,由于我根据句点分割了字符串,所以我不想丢失缩写。 回答1 解析句子绝非易事,即使对于像英语这样的拉丁语言也是如此。 像您在问题中概述的那样幼稚的方法经常会失败,以至于在实践中被证明是无用的。 更好的方法是使用配置了正确的Locale的BreakIterator。 BreakIterator iterator = BreakIterator.getSentenceInstance(Locale.US); String source = "This is a test. This is a T.L.A. test. Now with a Dr. in it."; iterator.setText(source); int start = iterator.first(); for (int
  • 在所有空格处拆分字符串(Splitting a string at all whitespace)
    问题 我需要在所有空格处拆分一个字符串,它应该只包含单词本身。 我怎样才能在 vb.net 中做到这一点? 制表符、换行符等必须全部拆分! 这已经困扰了我很长一段时间,因为我制作的语法荧光笔完全忽略了每一行中的第一个单词,除了第一行。 回答1 String.Split()(无参数)在所有空格(包括 LF/CR)上进行拆分 回答2 试试这个: Regex.Split("your string here", "\s+") 回答3 如果你想避免 regex ,你可以这样做: "Lorem ipsum dolor sit amet, consectetur adipiscing elit" .Split() .Where(x => x != string.Empty) Visual Basic 等效项: "Lorem ipsum dolor sit amet, consectetur adipiscing elit" _ .Split() _ .Where(Function(X$) X <> String.Empty) Where()很重要,因为如果您的字符串有多个相邻的空格字符,它会删除Split()产生的空字符串。 在撰写本文时,当前接受的答案 (https://stackoverflow.com/a/1563000/49241) 没有考虑到这一点。 回答4 String.Split(
  • 如何在反斜杠处分割Java字符串(How to split a java string at backslash)
    问题 String fname="C:\textfiles\db\query\query.txt"; 这是我需要将其拆分的字符串。 我尝试了这个 String [] items=fname.split("\"); 但是没有用。 String [] items=fname.split("\\"); also not working... 如何拆分此字符串... 回答1 首先,您不能在有问题的地方输入字符串 String fname="C:\textfiles\db\query\query.txt"; 这应该替换为 String fname="C:\\textfiles\\db\\query\\query.txt"; 因为反斜杠(“ \”)也需要转义。 最后,您需要执行以下操作来拆分它们: String fname="C:\\textfiles\\db\\query\\query.txt"; String[] items= fname.split("\\\\"); System.out.println(Arrays.toString(items)); 希望这可以帮助。 回答2 “拆分”期望RegEx。 使用split的最佳方法是使用“ Pattern.quote” String separator = "\\"; String value = "C:\\Main\\text.txt"
  • javascript在特殊字符处分割字符串(javascript splitting a string at special character)
    问题 我试图“智能地”预先填写表格,我想根据用户的电子邮件地址预先填写名字和姓氏输入,例如, jon.doe@email.com返回Jon Doe jon_doe@email.com返回乔恩·杜 jon-doe@email.com返回Jon Doe 我设法在@之前获取了字符串, var email = letters.substr(0, letters.indexOf('@')); 但是当分隔符可以是多个值时,无法解决如何split(),我可以做到这一点, email.split("_") 但是如何在其他电子邮件地址上分割有效的特殊字符? 回答1 JavaScript的字符串拆分方法可以使用正则表达式。 例如,以下内容将拆分为. , -和_ 。 "i-am_john.doe".split(/[.\-_]/) 返回以下内容。 ["i", "am", "john", "doe"] 回答2 您可以对要分割的内容使用正则表达式。 例如,您可以拆分任何非字母的内容: var parts = email.split(/[^A-Za-z]/); 演示:http://jsfiddle.net/Guffa/xt3Lb9e6/ 回答3 您可以使用正则表达式拆分字符串。 匹配. , _或- ,可以使用字符类,例如[.\-_] 。 JavaScript中正则表达式的语法为/expression/
  • 如何将字符串拆分为列表?(How to split a string into a list?)
    问题 我希望我的Python函数拆分一个句子(输入)并将每个单词存储在列表中。 我当前的代码拆分句子,但不将单词存储为列表。 我怎么做? def split_line(text): # split the text words = text.split() # for each word in the line: for word in words: # print the word print(words) 回答1 text.split() 这足以将每个单词存储在列表中。 words已经是句子中单词的列表,因此不需要循环。 其次,这可能是一个错字,但是您的循环有点混乱。 如果您确实确实想使用附加,它将是: words.append(word) 不是 word.append(words) 回答2 在任何连续的空白运行中将字符串拆分为text 。 words = text.split() 在定界符","上以text拆分字符串。 words = text.split(",") words变量将是一个list ,其中包含分隔符上来自text的单词。 回答3 str.split() 返回字符串中的单词列表,使用sep作为分隔符...如果未指定sep或为None,则应用不同的拆分算法:连续空格的运行被视为单个分隔符,并且结果将包含如果字符串的开头或结尾有空格,则开头或结尾不得有空字符串。 >
  • 如何在javascript中的一定数量的字符后在空格处拆分字符串?(How do I split a string at a space after a certain number of characters in javascript?)
    问题 所以我有一个很好的长字符串,我需要在 Javascript 中在一定数量的字符后面的空格处拆分。 例如,如果我有 “你是狗,我是猫。” 并且我希望它在 10 个字符后拆分,但在下一个空格处......所以我希望下一个空格成为拆分点,而不是拆分狗。 我希望我写得很清楚,解释起来有点尴尬。 编辑:我需要将所有这些存储到一个数组中。 所以按照我的描述拆分字符串,但将它存储到一个我可以迭代的数组中。 抱歉造成混乱 - 就像我说的,描述起来有点奇怪。 回答1 考虑: str = "How razorback-jumping frogs can level six piqued gymnasts!" result = str.replace(/.{10}\S*\s+/g, "$&@").split(/\s+@/) 结果: [ "How razorback-jumping", "frogs can level", "six piqued", "gymnasts!" ] 回答2 .indexOf有一个from参数。 str.indexOf(" ", 10); 您可以分别使用以下方法获取拆分前后的字符串: str.substring(0, str.indexOf(" ", 10)); str.substring(str.indexOf(" ", 10)); 回答3 这是你追求的吗? http