自然言語の重複データを検出したかったのです。
CPANだとText::Levenshtein、Text::WagnerFischer、Text::Brewあたり。
でも遅いよ。
1対1でしか比較できないんで、重複してる可能性のあるデータが3件以上だと扱いに困る。というか、あきらめた。
Rubyだと標準でPermutationが入ったから楽な気がする。まあCPAN漁ればすぐ見つかるけど。
でも処理量が可及的速やかに増大するのでちょっと悩むところ。無視をしても明らかに遅いのに。
事前にURL消したりHTMLタグ消したり改行文字と空白文字消すとかしといたほうがよさげ。
編集距離出して、全体の何%が編集されたか出して、それを閾値にして、という。
めどい。
なんか魔法の関数はないんですかね。
結論:自然言語を使うのをあきらめたい。
こんな感じか。なんつーかコードに締まりがないが。
use strict;
use warnings;
use utf8;
use Encode qw(decode encode);
use Text::WagnerFischer qw();
use DBI;
my $http_pat = qr/s?https?:\/\/[-_.!~*'()a-zA-Z0-9;\/?:\@&=+\$,%#]+/;
sub db_connect {
return DBI->connect('DBI:mysql:foo:bar', 'foo', 'bar') or die "can't connect";
}
sub getdata {
my $id = shift;
my $dbh = db_connect();
my $sth = $dbh->prepare("select id, content from data");
my $rv = $sth->execute();
my %x = ();
while (my @data = $sth->fetchrow_array()) {
$x{$data[0]} = decode("eucjp", $data[1]);
}
$sth->finish;
$dbh->disconnect;
return %x;
}
sub strip {
my $x = shift;
$x = strip_html($x) if $x;
$x = strip_ex_url($x) if $x;
$x = strip_cr($x)if $x;
return $x;
}
sub strip_html {
my $x = shift;
$x =~ s/<.+?>//sg;
return $x;
}
sub strip_ex_url {
my $x = shift;
my $ret = '';
for my $y (split /\n/, $x) {
if (my @http = $y =~ m/$http_pat/g) {
$ret .= $http[0] . "\n";
} else {
$ret .= $y ."\n";
}
}
return $ret;
}
sub strip_cr {
my $x = shift;
$x =~ s/[\n ]//g;
return $x;
}
my %data = getdata(); #DBから読んでくる
my %group = ();
# 言及しているURLでグルーピング
while (my ($key, $value) = each %data) {
if (my($http,) = ($value =~ m/$http_pat/g)) {
$group{$http} = [] unless exists $group{$http};
push @{$group{$http}}, $key;
}
}
my $threshold = 0.2;
while (my($key, $value) = each %group) {
if (@$value == 2) { # 似ている可能性がある記事が2個のときだけ比較
my $x1 = $data{$value->[0]};
my $x2 = $data{$value->[1]};
my $distance = Text::WagnerFischer::distance($x1, $x2);
if ($distance / length($x1) > $threshold && $distance / length($x2) > $threshold) {
print "$value->[0] resemble $value->[1]\n";
}
}
}
とりあえず気付いたのは、単語の言い換えにものすごく弱い。文字コード・エンコード・文字セット・文字集合の類とか、エンコードと符号化、Canonとキヤノン、Linuxとリナックスとか。ドラッグアンドドロップとDnDとか。
編集距離では普通の人とルー大柴は比較できないということだな。
これで何をするかと言うと、こういう画面があって(左ツリー右テキスト)
、左でアイテムをクリックするとその内容が右に出て、重複してるなーと思ったら削除とかやってたんだけど、微妙な差のが多数あったので、カッとなってある程度自動で取捨選択したくなったんよ。少なくとも件数は減ったよ。気付いたけど、割合出すとこ間違ってたよ……。直したよ……。
ValoのSK1を買ってから2年ぶりのニューブーツ。Valoブーツも、肉抜きとかトゥカットとか耐久性が落ちそうなことをしている割に、ソール換えるかどうかちょっと悩むぐらいでまだまだいけるけど、どうしても小さくて軽いブーツを試したくなって買っちゃった……。
足型があからさまに幅広甲高のため、これまではかなり余裕を見てUS10にしてたのだが、今回はとにかく軽くて小さいやつが欲しかったので、試しにUS9をDeeportから購入。最初は足が入らないかと思ったけど、とにかく紐を緩めてタンもガバっと出したら履けた。レーシングは進化してるけど、やっぱちょっと面倒くさい。あと甲高なせいでシェルから足の甲がはみ出るのだが、ちょうどそこのシェルとライナーの重なりとが当たると痛い。タンをずらせば問題ないけど、ホント甲高なんだなーと思ったりす。
つま先は結構余裕がある。US10のValoブーツのライナーが傷んだので純正からJugに替えたところ、つま先が圧倒的に狭くなったから、Razors SL US9のほうが余裕あるのかも。
サイズ小さいのを選んだせいもあるけど軽い。あとGC FeatherLiteフレームはものすごく軽い。
もう売っちゃったけど、記憶の中のUSD UFS Throneと比べると、シェル自体がすごい柔らかい。Valoのシェルは結構薄くて単体だとフニャフニャな感じだけど、それより厚みがありつつ、指で押して曲がるくらい柔らかい。カフも柔らかい。全体的に粘りがある柔らかさというか、なんとも絶妙な感じ。
バックスライドプレートに最初からついてるスポットは狭くてすごい深い。単管パイプにハマりきらないくらいというか。ソウルプレートがバックスライドプレートより2mmくらい出っ張ってるんで、ちょっと外れてもなんとかなるみたい。ソウルからビスが浅いところにあるのはどうなのかなと思うので、これは様子見。
噂の吸音材は普通の布っぽかったけど効果はあるようだ。
滑った感じもグラインドもまあ普通というか、今までできてたことはそのままできる。ミニミニランプでだけど、初めてアリウープトップソールができたから、やはりブーツの性能とかあるんかなーという気もする。
ちなみに、ほとんどのブーツ、パーツの売価自体は海外のほうが圧倒的に安いので、輸入も考えたんだけど、このブーツの場合は送料を考慮すると数千円しか差がなかった(32000JPYに対して350USDくらい)し、国内のショップで買うほうがいいよなあと思ったり色々。特にドルが安いのでAggressiveMallあたりで買うほうがユーロ圏より安い。しかし輸入は船便に当たるといつ届くかわからないとか、何か合った時の手続きの不安とか、色々あって心配だとは思う。UPSとかにすると不安感はなくなるけど送料上がるし、ぐぬぬ。
2012-12-23 追記:4時間連続で滑走したところ、足の甲が痛くて耐えられなくなったのでなんとかしたい。足の甲内側の関節ぽいとこがほんとヤバいというか、もう骨が変形しとる気もする…。シェル出しするか、クッション挟んで浮かすとかか。