perl通过字符串相似性聚类自定义排序

时间:2015-06-22 15:44:49

标签: perl sorting levenshtein-distance

在Perl中,我想对不同长度字符串的集合进行排序 以一种自动将类似字符串混为一谈的方式。

直观地说,我想我需要对每一对进行一些距离测量 然后是一个按距离分组的聚类程序。

我的字符串数量总是很小而且很短,请参阅 以下示例。

是否有一种简单的方法可以满足我的需求 # Added: ... # maximal line length when calling readline(). This is to prevent # reading arbitrary length lines. RFC 1939 limits POP3 line length to # 512 characters, including CRLF. We have selected 2048 just to be on # the safe side. _MAXLINE = 2048 ... # in_getline()... if len(self.buffer) > _MAXLINE: raise error_proto('line too long')

sort_magic_here

1 个答案:

答案 0 :(得分:1)

自定义排序采用两个输入,执行'比较'并以-1,0或1响应,具体取决于它们是在之前,之后还是相等。

排序是为了制作位置顺序而设计的,而不是真正用于“分类模糊相似的东西”。

你有Text::Levenshtein模块可以快速让你计算 - 但你必须做一些更复杂的事情,因为你需要在决定排序之前将每个单词与每个单词进行比较。但坦率地说,对于任何“类似词语”的比较,你都会遇到同样的问题。

在此,您将开始研究图论和基于此的分组。这是一个相当复杂的问题 - 它远不像'正义'排序那样微不足道。

我会看 之类的东西:

#!/usr/bin/perl
use strict;
use warnings;

use Text::Levenshtein qw ( distance );
use Data::Dumper;

my @list = (
    "JK_HJ_Lancaster",      "SY4_TS_HJ_1000ng",
    "NB_E_200cc_caHJ_Rep1", "HB_E_100cc_caHJ_Rep1",
    "HB_E_200cc_caHJ_Rep1", "Normal_Lancaster",
    "NB15_OP_HJ_1000ng",    "Zoey_HJ_Slough",
    "NB_E_100cc_caHJ_Rep1", "Normal_Slough",
    "JK_caHJ_Slough",       "Zoey_HJ_Lancaster"
);

my %distances;

foreach my $elem (@list) {
    foreach my $compare (@list) {
        next if $elem eq $compare;
        my $distance = distance( $elem, $compare );
        $distances{$elem}{$compare} = $distance;
    }
}

print Dumper \%distances;

my %seen;
my ($cursor) = sort @list;

while ($cursor) {
    print "$cursor\n";
    $seen{$cursor}++;
    my @near_words_in_order =
        sort { $distances{$cursor}{$a} <=> $distances{$cursor}{$b} }
        keys %{ $distances{$cursor} };

    #      print @near_words_in_order;
    last unless @near_words_in_order;
    while ( $seen{$cursor} ) {
        $cursor = shift(@near_words_in_order) // 0;
    }
}

结果如下:

HB_E_100cc_caHJ_Rep1
HB_E_200cc_caHJ_Rep1
NB_E_200cc_caHJ_Rep1
NB_E_100cc_caHJ_Rep1
NB15_OP_HJ_1000ng
SY4_TS_HJ_1000ng
Zoey_HJ_Slough
JK_caHJ_Slough
Normal_Slough
Normal_Lancaster
JK_HJ_Lancaster
Zoey_HJ_Lancaster

至少与您要求的群体相似。您可以更高效地使用它,因为您不需要计算所有距离,这会降低算法的复杂性。但是你也会根据接近度和起点得到不同的群体。