java list 高效比较_java-比较字符串列表相似性的快速算法

给我一个包含90,000多个名字的列表.我要检查具有> = 50%相似性的名称,并将结果以以下格式写入文件:

ID 1,ID 2,相似度百分比.

我已经有一个检查相似性的算法,但是遍历整个列表需要花费很多时间.有人可以提供快速算法来比较名称吗?

下面是代码

public static void main(String[] args) throws IOException {

List list = new ArrayList<>();

int count = 0;

FileWriter f = new FileWriter(new File("output.txt"));

StringBuilder str = new StringBuilder();

Scanner scanner = new Scanner(new File("name.csv"));

while (scanner.hasNextLine()) {

count ;

list.add(scanner.nextLine());

}

long start = System.currentTimeMillis();

//

for (int i = 0; i < list.size(); i ) {

for (int j = i 1; j < list.size(); j ) {

int percent = StringSimilarity.simi(list.get(i), list.get(j));

if (percent >= 50) {

str.append("ID " i ",ID " j "," percent " percent");

str.append("\n");

}

}

}

long end = System.currentTimeMillis();

f.write(str.toString());

System.out.println((end - start) / 1000 " second(s)");

f.close();

scanner.close();

}

public static String getString(String s) {

Pattern pattern = Pattern.compile("[^a-z A-Z]");

Matcher matcher = pattern.matcher(s);

String number = matcher.replaceAll("");

return number;

}

这是数据外观的一个示例…..名称存储在中. csv文件,因此我读取了文件并将名称存储在列表中.

名,姓,其他名,母亲的名

金斯利,埃兹,本,西西

Eze,Daniel,Ben,Julie

乔恩·史密斯,凯莉,乔

约瑟夫·谭·切丽

约瑟夫·坦·杰斯·谢丽

….等等

一个人至少可以拥有3个名字…..就像我之前提到的,该程序是检查名字的相似度,因此在比较ID 1和ID 2时,“ ben”是常见的,“ eze”是常见的,因此它们有50%的相似度.

比较id 4和id 5,相似度为75%….因为即使id 4没有3名,它们也有3个相同的名字.

所以问题是…在使用两个for循环进行相似性检查期间,我从第一个id开始,并通过其余90,000个名称进行检查,并保存与之具有> = 50%相似性的id,然后进行下一个id 2并做同样的事情……依此类推

解决方法:

假定相似度函数是最佳的:如果11个字母中的6个不同,则只需简单地返回即可,例如0.

一种小改进是不使用StringBuilder并跳过已经找到的匹配项.这有点关键,因为它可能是A≈B∧B≈C∧A≉C,因此有些匹配项会丢失.

Charset charset = StandardCharsets.ISO_8859_1; // Better UTF_8

Path inputPath = Paths.get("names.txt");

List list = Files.readAllLines(inputPath, charset);

Path outputPath = Paths.get("output.txt");

try (PrintWriter out = new PrintWriter(Files.newBufferedWriter(path, charset))) {

int n = list.size();

for (int i = 0; i < n; i) {

list.set(i, normalize(list.get(i)));

}

for (int i = 0; i < n; i) {

String ithWord = list.get(i);

for (int j = i 1; j < n; j) {

String jthWord = list.get(j);

if (jthWord != null) {

int perc = similarity(ithWord, list.get(j));

if (similarity >= 50) {

out.printf("ID %d,ID %d,%d percent or greater%n", i, j, perc);

list.set(j, null); // Skip it for other i

}

}

}

}

}

可以使用Java 8的并行性:

final List list = ...

IntStream.range(0, list.size())

.parallelStream()

.map(i -> ...

...

但这不会改变二次复杂度.

这将有助于对列表进行排序,并从第ith个单词得出所有前缀均在90%范围内的前缀.不幸的是50%不可行(n超过n / 2).

我会要求其他要求,例如听起来相似,最多3个错字或类似的错字.或在晚上运行.来源:https://www.icode9.com/content-1-562051.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值