我需要一些帮助解决这个问题。
我有两个脱节的字符串列表:list A = {a1, ..., an}
和list B = {b1, ..., bn}
列表的一个元素可以是一个简单的单词,如“人工”或“智能”,或者它可以通过更多的词来复合,如“人工智能”。
我还有一个包含很多单词的句子。其中一些属于两个列表中的一个。
我要做的是计算两个列表中两个字符串在同一个句子中出现的次数。
问题在于,如果我在句子中找到像人工智能这样的词,那么要考虑的正确词语只是“人工智能”(而非“人为”或“智能”)
我正在考虑将包含在句子中的列表中的每个单词添加到树集中,然后按长度排序并仅使用最长的单词,但我不认为解决方案非常好用和高效。 / p>
目前代码看起来像这样(但它仍然存在我正在谈论的问题)
// iterates on the words from the list A
for (String a: A)
// if the phrase contains the word
if (phrase.matches(".*\\b" + a + "\\b.*")
// iterates on the words from the list B
for (String b: B)
// if the phrase contains the word
if (phrase.matches(".*\\b" + b + "\\b.*")
// do stuffs
你有什么建议吗?谢谢!
答案 0 :(得分:1)
我不确定我是否完全了解您的要求,但如果您只需要计数,则可以对列表中的字符串赋予权重。例如,如果您有条目
artificial -> 1
intelligence -> 1
artificial intelligence -> -1
如果句子包含“人工智能”,则所有三个都匹配,给出权重总和= 1。
这需要一些预处理来计算字符串的正确权重。
答案 1 :(得分:1)
我的想法是跟踪所考虑的单词,然后清理。
尝试这样的事情:
int counter = 0;
List<String[]> h = new ArrayList<String[]>();
HashSet<String> words = new HashSet<String>();
// iterates on the words from the list A
for (String a: A)
// if the phrase contains the word
if (phrase.matches(".*\\b" + a + "\\b.*"))
// iterates on the words from the list B
for (String b: B)
// if the phrase contains the word
if (phrase.matches(".*\\b" + b + "\\b.*")) {
h.add(new String[]{a,b});
words.add(a);
words.add(b);
}
// clean up:
// 1. clean words
for (String i:words) {
// in words, keep only strings that are not contained by others
}
// 2. clean h
for (String[] i : h) {
// if i[0] or i[1] are both in words, then
// increment counter... or whatever you want
}
希望我明白你的问题
答案 2 :(得分:1)
您有2个列表。对于列表中的每个单词,都会创建从第一个单词到列表中其余单词的映射。例如,如果您在此列表中有“人工智能”,“蝙蝠洞穴”,“狗”,则将其存储为:
"artificial" => { "artificial intelligence" }
"bat" => { "bat cave" }
"dog" => { "dog" }
这将是第一步。预处理列表以获取列表中其余单词的第一个字的映射。
现在,当您的行包含“人工智能很酷”这样的声明时。您将该行与\w
分开。你得到的话。我们遇到的第一个词是“人为的”。我们查看之前获得的两张地图。所以我们在其中一张地图中看到artificial
的关键字。我们知道该行中的下一个词是什么。不过,我们希望与最长的比赛相匹配。所以我们比较得到与artificial
对应的单词列表。并使最长的子串匹配。我们一起找artificial intelliegence
,因为我们正在寻找最长的匹配。然而,我们重复第二个清单的过程。根据更长的时间,我们选择它是属于列表1还是列表2。
以下是一些示例代码。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class WordSplits {
public static Map<String, List<String>> first2rest(List<String> wordList) {
Map<String, List<String>> first2RestWords = new HashMap<String, List<String>>();
for (String word : wordList) {
// TODO Make it use Pattern. Sample demo. Get the first word of
// every string.
String splits[] = word.split("\\W");
String firstWord = splits[0];
List<String> restWords = first2RestWords.get(firstWord);
if (restWords == null) {
restWords = new ArrayList<String>();
}
restWords.add(word);
// store the complete pattern nevertheless
first2RestWords.put(firstWord, restWords);
}
return first2RestWords;
}
public static Map<String, List<Integer>> longestSubstring(String line,
List<String> first, List<String> second) {
Map<String, List<Integer>> occurences = new LinkedHashMap<String, List<Integer>>();
Map<String, List<String>> first2RestWords = first2rest(first);
Map<String, List<String>> second2RestWords = first2rest(second);
Matcher wordMatcher = Pattern.compile("\\w+").matcher(line);
for (int start = 0; start < line.length() && wordMatcher.find(start);) {
String word = wordMatcher.group();
String maxWordFirst = "", maxWordSecond = "";
if (first2RestWords.containsKey(word)) {
maxWordFirst = longestMatch(
line.substring(wordMatcher.start()),
first2RestWords.get(word));
}
if (second2RestWords.containsKey(word)) {
maxWordSecond = longestMatch(
line.substring(wordMatcher.start()),
second2RestWords.get(word));
}
if (maxWordFirst.length() > 0 || maxWordSecond.length() > 0) {
if (maxWordFirst.equals(maxWordSecond)) {
System.out.println("Belongs to both the lists : " + maxWordFirst);
} else {
if (maxWordFirst.length() > maxWordSecond.length()) {
System.out.println("Belongs to first list: " + maxWordFirst);
} else if (maxWordSecond.length() > maxWordFirst.length()) {
System.out.println("Belongs to second list: " + maxWordSecond);
}
}
} else {
System.out.println(word + " does not belong to any list");
}
// Take some action
start = wordMatcher.start() + Math.max(maxWordFirst.length(), maxWordSecond.length()) + 1;
start = Math.max(wordMatcher.end(), start);
}
return occurences;
}
public static String longestMatch(String line, List<String> wordList) {
String maxWord = "";
// poor way to compare
for (String word : wordList) {
if (line.startsWith(word) && word.length() > maxWord.length()) {
maxWord = word;
}
}
return maxWord;
}
public static void main(String[] args) {
longestSubstring("artificial intelligence is cool. bat.",
Arrays.asList("dog", "cow", "dog", "artificial intelligence", "bat"),
Arrays.asList("artificial", "hound", "cool", "bat", "dog hound"));
}
}
要处理的行是"artificial intelligence is cool. bat."
l1 = `"dog", "cow", "dog", "artificial", "artificial intelligence", "bat"`
l2 = `"intelligence", "hound", "cool", "bat", "dog hound"`
程序输出
Belongs to first list: artificial intelligence
is does not belong to any list
Belongs to second list: cool
Belongs to both the lists : bat
有很多优化要做。
答案 3 :(得分:0)
我想我找到了解决方案,你帮我思考了。
我能做的是分别在列表中迭代,并在句子中添加我在两个临时地图中找到的单词(具有计算权重的权重)。之后,我可以单独迭代这两个映射,如果字符串a1包含字符串a2,我将a2的权重减1。之后,我将获得2个包含正确权重的地图,我可以迭代它们,增加每对的共现。
我认为这应该有效!