首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在包含句子的列表中统计单词的出现

在包含句子的列表中统计单词的出现
EN

Stack Overflow用户
提问于 2016-01-25 06:44:13
回答 3查看 249关注 0票数 0

我在Java编程中遇到了一些问题,其中包括列表。基本上,我试图从一个包含几个句子的列表中计算出一个句子中每个单词的数量。包含句子的清单代码如下:

代码语言:javascript
运行
复制
List<List<String>> sort = new ArrayList<>();
for (String sentence : complete.split("[.?!]\\s*"))
{
    sort.add(Arrays.asList(sentence.split("[ ,;:]+"))); //put each sentences in list
}

该列表的输出如下:

代码语言:javascript
运行
复制
[hurricane, gilbert, head, dominican, coast]
[hurricane, gilbert, sweep, dominican, republic, sunday, civil, defense, alert, heavily, populate, south, coast, prepare, high, wind]
[storm, approach, southeast, sustain, wind, mph, mph]
[there, alarm, civil, defense, director, a, television, alert, shortly]

输出所需的应该如下所示(仅是一个示例)。它将输出列表中所有唯一的单词,并按句子计算出现的情况。

代码语言:javascript
运行
复制
Word: hurricane
Sentence 1: 1 times
Sentence 2: 1 times
Sentence 3: 0 times
Sentence 4: 0 times

Word: gilbert
Sentence 1: 0 times
Sentence 2: 2 times
Sentence 3: 1 times
Sentence 4: 0 times 

Word: head
Sentence 1: 3 times
Sentence 2: 2 times
Sentence 3: 0 times
Sentence 4: 0 times 

and goes on....

在上面的例子中,“飓风”一词在第一句中发生了一次,在第二句中发生了一次,在第三句中没有发生,在第四句中没有发生。如何实现输出?我在想一个二维矩阵来构建它们。任何帮助都将不胜感激。谢谢!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-01-25 07:18:27

这是一个可行的解决办法。我没有处理印刷问题。结果是一个Map -> Word,Array。其中Array包含从0索引的每个句子中的单词计数。在O(N)时间运行。在这里玩:https://repl.it/Bg6D

代码语言:javascript
运行
复制
    List<List<String>> sort = new ArrayList<>();
    Map<String, ArrayList<Integer>> res = new HashMap<>();

    // split by sentence
    for (String sentence : someText.split("[.?!]\\s*")) {
        sort.add(Arrays.asList(sentence.split("[ ,;:]+"))); //put each sentences in list
    }

    // put all word in a hashmap with 0 count initialized
    final int sentenceCount = sort.size();
    sort.stream().forEach(sentence -> sentence.stream().forEach(s -> res.put(s, new ArrayList<Integer>(Collections.nCopies(sentenceCount, 0)))));

    int index = 0;
    // count the occurrences of each word for each sentence.
    for (List<String> sentence: sort) {
        for (String s : sentence) {
            res.get(s).set(index, res.get(s).get(index) + 1);
        }
        index++;
    }

编辑:回答您的评论。

代码语言:javascript
运行
复制
  List<Integer> getSentence(int sentence, Map<String, ArrayList<Integer>> map) {
     return map.entrySet().stream().map(e -> e.getValue().get(sentence)).collect(Collectors.toList());
  }

然后你可以打电话

代码语言:javascript
运行
复制
List<Integer> sentence0List = getSentence(0, res);

但是,请注意,这种方法并不是最优的,因为它在O(K)时间内运行,K是句子的数量。对于小K,它是完全好的,但它没有刻度。你必须弄清楚你将如何处理这个结果。如果您需要多次调用getSentence,这不是正确的方法。在这种情况下,您将需要不同的数据结构。有点像

代码语言:javascript
运行
复制
Sentences = [
         {'word1': N, 'word2': N},... // sentence 1 
         {'word1': N, 'word2': N},... // sentence 2

]

因此,您可以轻松地访问每个句子的单词计数。

编辑2:调用此方法:

代码语言:javascript
运行
复制
  Map<String, Float> getFrequency(Map<String, ArrayList<Integer>> stringMap) {
    Map<String, Float> res = new HashMap<>();
    stringMap.entrySet().stream().forEach(e -> res.put(e.getKey()
                , e.getValue().stream().mapToInt(Integer::intValue).sum() / (float)e.getValue().size()));
    return res;
  }

将返回如下内容:

代码语言:javascript
运行
复制
{standard=0.25, but=0.25, industry's=0.25, been=0.25, 1500s=0.25, software=0.25, release=0.25, type=0.5, when=0.25, dummy=0.5, Aldus=0.25, only=0.25, passages=0.25, text=0.5, has=0.5, 1960s=0.25, Ipsum=1.0, five=0.25, publishing=0.25, took=0.25, centuries=0.25, including=0.25, in=0.25, like=0.25, containing=0.25, printer=0.25, is=0.25, t
票数 1
EN

Stack Overflow用户

发布于 2016-01-25 07:10:38

您可以通过首先为每个单词创建一个索引来解决问题。您可以使用Hashmap并将所有单个单词放在上面,这是您在文本中找到的(因此您不需要检查重复出现的情况)。

然后你可以迭代HashMap和检查每个句子中的每个单词。您可以通过使用列表的indexOf法来计数出现的次数。只要它返回大于-1的值,就可以计算出句子中的出现情况。此方法只返回第一个匹配项,因此

一些伪码就像:

数组语句=text.split(句子分隔符)

代码语言:javascript
运行
复制
for each word in text
    put word on hashmap

for each entry in hashmap
   for each sentence
       int count = 0
       while subList(count, sentence.length) indexOf(entry) > -1
          count for entry ++

注意到,这是非常贪婪的,根本不面向性能。哦,是的,也请注意,有一些java nlp库可能已经以面向性能和可重用的方式解决了您的问题。

票数 0
EN

Stack Overflow用户

发布于 2016-01-25 07:46:03

首先,您可以对句子进行分段,然后使用文本分段(如NLTK或斯坦福令牌程序)对它们进行标记。将字符串(包含句子)拆分成“?!”不是个好主意。“等”发生了什么?或“例如”发生在句子中间的事?分裂一个句子围绕“,;:”也不是一个好主意。你可以在句子中有很多其他的符号,比如引号,破折号等等。

分段和标记化之后,您可以将句子拆分到空间中,并将它们存储在List<List<String>>中。

代码语言:javascript
运行
复制
List<List<String>> sentenceList = new ArraList();

然后,对于索引,您可以创建一个HashMap<String,List<Integer>>

代码语言:javascript
运行
复制
HashMap<String,List<Integer>> words = new HashMap();

键是所有句子中的所有单词。可以按以下方式更新的值:

代码语言:javascript
运行
复制
for(int i = 0 ; i < sentenceList.size() ; i++){
    for(String w : words){
        if(sentence.contains(w)){
           List tmp = words.get(w);
           tmp.get(i)++; 
           words.put(w, tmp);
         }
    }
}

该解的时间复杂度为O(number_of_sentences*number_of_words),相当于O(n^2)。一个优化的解决方案是:

代码语言:javascript
运行
复制
for(int i = 0 ; i < sentenceList.size() ; i++){
    for(String w : sentenceList.get(i)){
        List tmp = words.get(w);
        tmp.get(i)++; 
        words.put(w, tmp);
    }
}

这具有O(number_of_sentences*average_length_of_sentences).的时间复杂性。由于average_length_of_sentences通常很小,这相当于O(n)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34986555

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档