天道酬勤,学无止境

Splitting text to sentences and sentence to words: BreakIterator vs regular expressions

I accidentally answered a question where the original problem involved splitting sentence to separate words.

And the author suggested to use BreakIterator to tokenize input strings and some people liked this idea.

I just don't get that madness: how 25 lines of complicated code can be better than a simple one-liner with regexp?

Please, explain me the pros of using BreakIterator and the real cases when it should be used.

If it's really so cool and proper then I wonder: do you really use the approach with BreakIterator in your projects?

评论

From looking at the code posted at that answer, it looks like BreakIterator takes into consideration the language and locale of the text. Getting that level of support via regex will surely be a considerable pain. Perhaps that is the main reason it is preferred over a simple regex?

The BreakIterator gives some nice explicit control and iterates cleanly in a nested way over each sentence and word. I'm not familiar with exactly what specifying the locale does for you, but I'm sure its quite helpful sometimes as well.

It didn't strike me as complicate at all. Just set up one iterator for the sentence level, another for the word level, nest the word one inside the second one.

If the problem changed into something different the solution you had on the other question might've just been out the window. However, that pattern of iterating through sentences and words can do a lot.

  1. Find the sentence where any word occurs the most repeated times. Output it along with that word
  2. Find the word used most times throughout the whole string.
  3. Find all words that occur in every sentence
  4. Find all words that occur a prime number of times in 2 or more sentences

The list goes on...

受限制的 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>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • Java简单句解析器(Java simple sentence parser)
    问题 有没有什么简单的方法可以在不添加任何库和 jar 的情况下用纯 Java 创建句子解析器。 解析器不应该只关心单词之间的空格,而是要更加聪明和解析: . ! ?,识别句子何时结束等。 解析后,只能将真实的单词全部存储在db或file中,而不能存储任何特殊字符。 非常感谢大家提前:) 回答1 您可能想从查看 BreakIterator 类开始。 来自 JavaDoc。 BreakIterator 类实现了用于查找文本中边界位置的方法。 BreakIterator 的实例维护当前位置并扫描文本,返回出现边界的字符索引。 在内部,BreakIterator 使用 CharacterIterator 扫描文本,因此能够扫描由实现该协议的任何对象保存的文本。 StringCharacterIterator 用于扫描传递给 setText 的 String 对象。 您可以使用此类提供的工厂方法来创建各种类型的中断迭代器的实例。 特别是,使用 getWordIterator、getLineIterator、getSentenceIterator 和 getCharacterIterator 来创建 BreakIterator,分别执行词、行、句子和字符边界分析。 单个 BreakIterator 只能处理一个单元(单词、行、句子等)。 您必须为要执行的每个单元边界分析使用不同的迭代器。
  • 在Java中将句子字符串转换为单词的字符串数组(Converting a sentence string to a string array of words in Java)
    问题 我需要我的Java程序采用类似以下的字符串: "This is a sample sentence." 并将其转换为一个字符串数组,如: {"this","is","a","sample","sentence"} 没有句号或标点符号(最好)。 顺便说一句,字符串输入始终是一个句子。 有没有一种我看不到的简便方法? 还是我们真的必须大量搜索空格并从空格之间的区域(即单词)创建新的字符串? 回答1 String.split()将完成您想要的大部分操作。 然后,您可能需要遍历单词以提取任何标点符号。 例如: String s = "This is a sample sentence."; String[] words = s.split("\\s+"); for (int i = 0; i < words.length; i++) { // You may want to check for a non-word character before blindly // performing a replacement // It may also be necessary to adjust the character class words[i] = words[i].replaceAll("[^\\w]", ""); } 回答2 现在,只需使用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
  • BreakIterator如何在Android中工作?(How does BreakIterator work in Android?)
    问题 我正在用Android(蒙古语的自定义垂直脚本TextView)制作自己的文本处理器。 我以为自己必须找到所有换行位置才能实现换行,但是后来我发现了BreakIterator。 这似乎找到了各种语言中的字符,单词,行和句子之间的所有可能的中断。 我正在尝试学习如何使用它。 该文档比一般文档更有帮助,但仅通过阅读仍然难以理解。 我还找到了一些教程(请参阅此处,此处和此处),但是它们缺少我所寻找的输出的完整说明。 我添加了这个问答形式的答案,以帮助自己学习如何使用BreakIterator 。 我将其设置为Java之外的Android标签,因为它们之间显然存在一些差异。 此外,Android现在支持ICU BreakIterator,将来的答案可能会解决此问题。 回答1 BreakIterator可用于查找字符,单词,行和句子之间的可能间隔。 这对于诸如将光标移动到可见字符,双击以选择单词,三次单击以选择句子以及换行等操作很有用。 样板代码 下面的示例中使用以下代码。 只需调整第一部分即可更改BreakIterator的文本和类型。 // change these two lines for the following examples String text = "This is some text."; BreakIterator boundary =
  • 将段落拆分为带有标题和数字的句子(Split paragraph into sentences with titles and numbers)
    问题 我在 Java 中使用 BreakIterator 类将段落分成句子。 这是我的代码: public Map<String, Double> breakSentence(String document) { sentences = new HashMap<String, Double>(); BreakIterator bi = BreakIterator.getSentenceInstance(Locale.US); bi.setText(document); Double tfIdf = 0.0; int start = bi.first(); for(int end = bi.next(); end != BreakIterator.DONE; start = end, end = bi.next()) { String sentence = document.substring(start, end); sentences.put(sentence, tfIdf); } return sentences; } 问题是当段落包含标题或数字时,例如: “罗伯茨教授试图通过编写 1.200 行代码来解决问题。” 我的代码将产生的是: sentences : Prof Roberts trying to solve a problem by writing a 1 200
  • 如何将不使用空格的泰语句子拆分成单词?(How to split a Thai sentence, which does not use spaces, into words?)
    问题 如何从泰语句子中拆分单词? 英语我们可以按空格分割单词。 示例: I go to school , split = ['I', 'go', 'to' ,'school']仅通过查看空间来拆分。 但是泰语没有空格,所以不知道怎么做。示例吐我要去学校从txt文件到['I' 'will' 'go' 'school' 'study'] = output another txt 文件。 是否有任何程序或库可以识别泰语单词边界和拆分? 回答1 2006 年,有人为 Apache Lucene 项目贡献了代码来完成这项工作。 他们的方法(用 Java 编写)是使用 BreakIterator 类,调用getWordInstance()来获取基于字典的泰语单词迭代器。 另请注意,对 ICU4J 项目有明确的依赖性。 我在下面粘贴了他们代码的相关部分: private BreakIterator breaker = null; private Token thaiToken = null; public ThaiWordFilter(TokenStream input) { super(input); breaker = BreakIterator.getWordInstance(new Locale("th")); } public Token next() throws
  • Python-RegEx,用于将文本拆分为句子(句子加标记)(Python - RegEx for splitting text into sentences (sentence-tokenizing) [duplicate])
    问题 这个问题已经在这里有了答案: 如何将文本拆分为句子? (15个答案) 2年前关闭。 我想从字符串中列出句子列表,然后将其打印出来。 我不想使用NLTK来做到这一点。 因此,它需要在句子末尾的句点而不是小数点,缩写或名称的标题或句子中有.com的情况下进行拆分。这是对正则表达式的尝试不起作用。 import re text = """\ Mr. Smith bought cheapsite.com for 1.5 million dollars, i.e. he paid a lot for it. Did he mind? Adam Jones Jr. thinks he didn't. In any case, this isn't true... Well, with a probability of .9 it isn't. """ sentences = re.split(r' *[\.\?!][\'"\)\]]* *', text) for stuff in sentences: print(stuff) 示例输出应该看起来像什么 Mr. Smith bought cheapsite.com for 1.5 million dollars, i.e. he paid a lot for it. Did he mind? Adam Jones Jr. thinks
  • Score each sentence in a line based upon a tag and summarize the text. (Java)
    I'm trying to create a summarizer in Java. I'm using the Stanford Log-linear Part-Of-Speech Tagger to tag the words, and then, for certain tags, I'm scoring the sentence and finally in the summary, I'm printing sentences with a high score value. Here's the code: MaxentTagger tagger = new MaxentTagger("taggers/bidirectional-distsim-wsj-0-18.tagger"); BufferedReader reader = new BufferedReader( new FileReader ("C:\\Summarizer\\src\\summarizer\\testing\\testingtext.txt")); String line = null; int score = 0; StringBuilder stringBuilder = new StringBuilder(); File tempFile = new File("C:\
  • 从复杂(混合)句子中提取简单句子的算法?(algorithm to extract simple sentences from complex(mixed) sentences?)
    问题 有没有一种算法可以用来从段落中提取简单的句子? 我的最终目标是稍后对生成的简单句子运行另一种算法来确定作者的情绪。 我已经从 Chae-Deug Park 等来源研究过这个,但没有人讨论准备简单的句子作为训练数据。 提前致谢 回答1 我刚刚使用了 openNLP。 public static List<String> breakIntoSentencesOpenNlp(String paragraph) throws FileNotFoundException, IOException, InvalidFormatException { InputStream is = new FileInputStream("resources/models/en-sent.bin"); SentenceModel model = new SentenceModel(is); SentenceDetectorME sdetector = new SentenceDetectorME(model); String[] sentDetect = sdetector.sentDetect(paragraph); is.close(); return Arrays.asList(sentDetect); } 例子 //Failed at Hi. paragraph = "Hi. How are
  • Javascript 将 unicode 句子拆分成单词(Javascript splits unicode sentence into words)
    问题 我正在使用以下正则regexp将句子拆分为单词数组。 /\b(?![\s.,:;'"])/ 它适用于非 unicode 句子,但在接下来的句子中失败。 læseWEB læser teksten på dit website op. 我期待着 ['læseWEB ', 'læser ', 'teksten ', 'på ', 'dit ', 'website ', 'op.']. 但我得到 ['l', 'æ', 'se', 'WEB', 'l', 'æ', 'ser', 'teksten', 'p', 'å', 'dit','website', 'op'] 我知道 javascript 在 unicode 操作方面存在问题。 我打算使用 XRegExp javascript 插件,但我找不到我正在寻找的确切解决方案。 回答1 JavaScript 中\b的定义基于\w的定义,即[A-Za-z0-9_] (仅涵盖 ASCII 字符)。 如果您将 XRegExp 与 Unicode Category + Unicode Properties 附加组件一起使用,您可以使用以下代码匹配(而不是拆分)字符串: XRegExp.matchChain("læseWEB læser teksten på dit website op.", [XRegExp("[\\p{Alphabetic}
  • 如何检查我的列表中是否有任何单词包含在文本中(How to check if any word in my List<string> contains in text)
    问题 我有一个 List<string> words = new List<string> {"word1", "word2", "word3"}; 我想使用 linq 检查我的字符串是否包含这些单词中的任何一个; 喜欢: var q = myText.ContainsAny(words); 第二,如果我也有一个句子列表: List<string> sentences = new List<string> { "sentence1 word1" , "sentence2 word2" , "sentence3 word3"}; 并且还需要检查这些句子中是否有任何一个包含这些单词! var q = sentences.Where(s=>words.Any(s.text)).... 回答1 如果您只需要检查子字符串,您可以使用简单的 LINQ 查询: var q = words.Any(w => myText.Contains(w)); // returns true if myText == "This password1 is weak"; 如果要检查整个单词,可以使用正则表达式: 匹配所有单词的分离的正则表达式: // you may need to call ToArray if you're not on .NET 4 var escapedWords = words
  • 如何将文本解析成句子(How to parse text into sentences)
    问题 我试图将一个段落分解成句子。 到目前为止,这是我的代码: import java.util.*; public class StringSplit { public static void main(String args[]) throws Exception{ String testString = "The outcome of the negotiations is vital, because the current tax levels signed into law by President George W. Bush expire on Dec. 31. Unless Congress acts, tax rates on virtually all Americans who pay income taxes will rise on Jan. 1. That could affect economic growth and even holiday sales."; String[] sentences = testString.split("[\\.\\!\\?]"); for (int i=0;i<sentences.length;i++){ System.out.println(i); System.out.println(sentences[i]
  • Why is this simple Solr highlighting attempt failing?
    I've read the Solr highlighting wiki document several times, searched everywhere, but cannot get even basic highlighting to work with my Solr installation. I am running Solr 3.5 on the demo Jetty 6.1 server. I have indexed 250K documents, and am able to search them just fine. Other than configuring my document field definitions, most of the Solr configuration is "stock," although I have temporarily commented out the solrconfig.xml's "Highlighting defaults" to make sure they aren't causing this problem: <!-- Highlighting defaults <str name="hl">on</str> <str name="hl.fl">title snippet</str>
  • 如何用转义的空格拆分句子?(How to split a sentence with an escaped whitespace?)
    问题 除了转义的空格外,我想使用空格作为分隔符来拆分我的句子。 使用 boost::split 和 regex,我该如何拆分它? 如果不可能,还有什么办法? 例子: std::string sentence = "My dog Fluffy\\ Cake likes to jump"; 结果: 我的狗蓬松\蛋糕喜欢到跳 回答1 三种实现: 用升压精神使用 Boost 正则表达式手写解析器 用升压精神 这是我如何使用 Boost Spirit 做到这一点。 这似乎有点矫枉过正,但经验告诉我,一旦拆分输入文本,您可能需要更多的解析逻辑。 当您从“只是拆分标记”扩展到具有生产规则的真正语法时,Boost Spirit 会大放异彩。 住在 Coliru #include <boost/spirit/include/qi.hpp> namespace qi = boost::spirit::qi; int main() { std::string const sentence = "My dog Fluffy\\ Cake likes to jump"; using It = std::string::const_iterator; It f = sentence.begin(), l = sentence.end(); std::vector<std::string> words
  • JavaScript 正则表达式和捕获组(JavaScript Regular Expressions and Capture Groups)
    问题 我是 JavaScript 中正则表达式的新手,并且无法从文本字符串中获取匹配数组,如下所示: Sentence would go here -foo -bar Another sentence would go here -baz -bat 我想得到这样的匹配数组: match[0] = [ 'foo', 'bar' ] match[1] = [ 'baz', 'bat' ] 总而言之,我正在寻找的是: “任何出现在句子之后的破折号+单词(-foo、-bar 等) ” 任何人都可以提供一个公式来捕获所有迭代而不是最后一个迭代,因为重复捕获组显然只会捕获最后一个迭代。 如果这是一个愚蠢的问题,请原谅我。 如果有人想给我发送一些测试,我正在使用 regex101 回答1 如果足够,只需匹配以-开头并以换行符开头的两行。 \n-(.*)\r?\n-(.*) 请参阅 regex101 中的正则表达式演示。 要获得匹配使用 exec() 方法。 var re = /\n-(.*)\r?\n-(.*)/g; var m; var str = 'Sentence would go here\n-foo\n-bar\nAnother sentence would go here\n-baz\n-bat'; while ((m = re.exec(str)) !== null) { if
  • Elasticsearch搜索高亮标签自定义
    Elasticsearch搜索高亮标签自定义 日常生活中我们使用搜索工具尝试查询一些信息的时候,常常可以看到返回的结果集中和我们查询条件相符合的字段被特殊的颜色所标记,这就是结果高亮显示。通过高亮显示用户可以明显的发现查询匹配的位置,ES使用highlight来实现搜索结果中一个或多个字段突出显示。 高亮显示需要字段中的内容,如果没有存储字段store=true,则加载实际的_source并从_source提取相关字段。 简单的例子 下面是一个简单的例子,使用的映射结构 PUT article/_mapping { "properties": { "article_type": { "type": "keyword" }, "article_title": { "type": "text" }, "content": { "type": "text" }, "date": { "type": "date", "format": ["yyyy-MM-dd HH:mm:ss"] }, "read_num": { "type": "integer" }, "comment_num": { "type": "integer" } } } 数据内容为自定义 {"index":{"_index":"article","_id":0}} {"article_type": "原创"
  • 分割档案-Java / Linux(Split File - Java/Linux)
    问题 我有一个大文件,包含将近2.5亿个字符。 现在,我想将其拆分为每个包含3000万个字符的部分(因此前8个部分将包含3000万个字符,最后一部分将包含1000万个字符)。 另一点是,我想在下一部分的开头包括每个文件的最后1000个字符(意味着第1部分的最后1000个字符附加在第二部分的开头-因此,第二部分包含3000万个1000个字符,依此类推)。 有人可以帮助我如何以编程方式(使用Java)或使用Linux命令(快速方式)进行操作。 回答1 一种方法是使用常规的unix命令来分割文件,并在前一个文件的最后1000个字节之前添加前缀。 首先分割文件: split -b 30000000 inputfile part. 然后,对于每个部分(忽略最远的部分,请从前一个文件的最后一个1000字节开始创建一个新文件: unset prev for i in part.* do if [ -n "${prev}" ] then tail -c 1000 ${prev} > part.temp cat ${i} >> part.temp mv part.temp ${i} fi prev=${i} done 在组装之前,我们再次遍历文件,忽略第一个文件并丢弃前1000个字节: unset prev for i in part.* do if [ -n "${prev}" ] then
  • 使用 Lucene SpanQueries 进行句子感知搜索(Sentence aware search with Lucene SpanQueries)
    问题 是否可以使用 Lucene SpanQuery 来查找术语“红色”、“绿色”和“蓝色”都出现在一个句子中的所有事件? 我的第一个(不完整/不正确)方法是编写一个分析器,将一个特殊的句子标记标记和句子的开头放置在与句子的第一个单词相同的位置,然后查询类似于以下内容: SpanQuery termsInSentence = new SpanNearQuery( SpanQuery[] { new SpanTermQuery( new Term (MY_SPECIAL_SENTENCE_TOKEN)), new SpanTermQuery( new Term ("red")), new SpanTermQuery( new Term ("green")), new SpanTermQuery( new Term ("blue")), }, 999999999999, false ); SpanQuery nextSentence = new SpanTermQuery( new Term (MY_SPECIAL_SENTENCE_TOKEN)); SpanNotQuery notInNextSentence = new SpanNotQuery(termsInSentence,nextSentence); 当然,问题在于nextSentence并不是真正的下一个句子
  • 在没有 split() 的情况下在 Python 中拆分字符串(Splitting strings in Python without split())
    问题 在不使用 split() 方法的情况下拆分字符串的其他方法是什么? 例如,如何在不使用 split() 方法的情况下将 ['This is a Sentence'] 拆分为 ['This', 'is', 'a', 'Sentence'] ? 回答1 sentence = 'This is a sentence' split_value = [] tmp = '' for c in sentence: if c == ' ': split_value.append(tmp) tmp = '' else: tmp += c if tmp: split_value.append(tmp) 回答2 如果需要,您可以使用正则表达式: >>> import re >>> s = 'This is a Sentence' >>> re.findall(r'\S+', s) ['This', 'is', 'a', 'Sentence'] \S代表任何非空白字符, +表示在一行中查找一个或多个这些字符。 re.findall将创建与该模式匹配的所有字符串的list 。 但是,实际上, s.split()是最好的方法。 回答3 一个递归版本,详细分解步骤: def my_split(s, sep=' '): s = s.lstrip(sep) if sep in s: pos = s.index
  • How to split a sentence into words and punctuations in java
    I want to split a given sentence of type string into words and I also want punctuation to be added to the list. For example, if the sentence is: "Sara's dog 'bit' the neighbor." I want the output to be: [Sara's, dog, ', bit, ', the, neighbour, .] With string.split(" ") I can split the sentence in words by space, but I want the punctuation also to be in the result list. String text="Sara's dog 'bit' the neighbor." String list = text.split(" ") the printed result is [Sara's, dog,'bit', the, neighbour.] I don't know how to combine another regex with the above split method to separate punctuations