我在列表中有一个关键字列表,我有来自某些来源的数据,这也是一个列表。
我想查找数据列表中是否存在任何关键字,如果是,则将这些关键字添加到另一个目标列表。
E.g。
关键字列表= SDK manager
数据列表= FIRSTNAME, LASTNAME, CURRENCY & FUND
从上面的示例中,我想制作一个包含关键字HUSBANDFIRSTNAME, HUSBANDLASTNAME, WIFEFIRSTNAME, SOURCECURRENCY & CURRENCYRATE.
的目标列表,但FIRSTNAME, LASTNAME & CURRENCY
不应该出现,因为它不存在于数据列表中。
我在下面有一个解决方案,通过使用两个for循环(一个在另一个内部)并使用String contains方法检查,但我想避免两个循环,尤其是一个在另一个循环中。
FUND
我的问题还有其他替代解决方案吗?
答案 0 :(得分:1)
尝试Aho-Corasick算法。该算法可以得到数据中每个关键字的出现次数(只需要它是否出现)。
复杂性为O(Sum(Length(Keyword)) + Length(Data) + Count(number of match))
。
以下是wiki-page:
在计算机科学中,Aho-Corasick算法是一个字符串搜索 由Alfred V. Aho和Margaret J. Corasick发明的算法。它是 一种字典匹配算法,用于定位a的元素 输入文本中的有限字符串集("字典")。它 同时匹配所有模式。算法的复杂性 是模式的长度加上长度的线性 搜索文本加上输出匹配的数量。
我在几年前就类似的情况实施了它(大约200行),并且效果很好。
如果您关心关键字是否出现,您可以为您的案例修改该算法,具有更好的复杂性:
O(Sum(Length(Keyword)) + Length(Data))
。
您可以从互联网上找到该算法的实现,但我认为理解该算法并自行实现它会对您有所帮助。
编辑:
我认为你想要消除两个循环,所以我们需要在一个循环中找到所有关键字。我们称之为Set Match Problem
一组模式(关键字)与文本(数据)匹配。您想要解决Set Match Problem
,那么您应该选择专为此案例设计的Aho–Corasick algorithm
。这样,我们将获得一个循环解决方案:
for (int i=0; i < dataList.size(); i++) {
targetSet.addAll(Ac.run(keywordsList));
}
您可以从here找到实施。
答案 1 :(得分:1)
这是使用regex
的单循环方法。您可以使用关键字构建模式,然后遍历dataList
并查看是否可以找到匹配项。
public static void main(String[] args) throws Exception {
List<String> keywords = new ArrayList(Arrays.asList("FIRSTNAME", "LASTNAME", "CURRENCY", "FUND"));
List<String> dataList = new ArrayList(Arrays.asList("HUSBANDFIRSTNAME", "HUSBANDLASTNAME", "WIFEFIRSTNAME", "SOURCECURRENCY", "CURRENCYRATE"));
Set<String> targetSet = new HashSet();
String pattern = String.join("|", keywords);
for (String data : dataList) {
Matcher matcher = Pattern.compile(pattern).matcher(data);
if (matcher.find()) {
targetSet.add(matcher.group());
}
}
System.out.println(targetSet);
}
结果:
[CURRENCY, LASTNAME, FIRSTNAME]