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