If I were to do this, instead of using a hash and naming the clasess, I would use an array of classes where each array is a class. Then to add works you look at each class and and the word to the first class where the average distance from the new word to each word in the collection is below a certain threshold. That is what I've done below. To make it even better you could scan every class and add it to the class that has the lowest average distance. I also only added the word once, and if its already added skipped it.

#!/usr/bin/perl use strict; use warnings; use Text::Levenshtein qw/fastdistance/; use Data::Dumper; my $classes = []; my $index = {}; my $limit = 0.5; sub avg_distance { my ($new_word, $class) = @_; my $distance = 0; for my $word (@$class) { $distance += fastdistance($new_word, $word); } return $distance / @$class; } sub put_or_create { my ($w) = @_; $w =~ s/[^a-z]//g; my $found=0; return if exists $index->{$w}; foreach my $class ( @$classes ) { if((avg_distance($w,$class)/length($w)) < $limit) { push @$class, $w; $index->{$w} = $class; $found = 1; last; }; }; if(! $found) { my $class = [$w]; push @$classes, $class; $index->{$w} = $class; }; }; #watch for an error opening the file open( my $file,"<", "possible_locations.txt") or die "Failed to open f +ile: $!"; my @locations = <$file>; #remove the line endings chomp(@locations); my $count = 0; for (@locations) { #last if ++$count/@locations > 0.2;#not all put_or_create($_) } for (@$classes) { print join(",", sort @$_), "\n"; }

This approaches might need some improvement. The first that comes to mind is add the word to the class/set that is closest, then divide that set up when the average distance becomes too great. I might even give that a shot as it sounds fun!


___________
Eric Hodges

In reply to Re: separating text words in similarity classes using levenshtein by eric256
in thread separating text words in similarity classes using levenshtein by spx2

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.