अस्पष्ट স্ট্রিং ম্যাচিংয়ের জন্য এমন কোনও প্রোগ্রাম রয়েছে, যা ম্যাচের স্কোর সরবরাহ করে?


17

আমার কাছে ফাইল Aএবং ফাইলে স্ট্রিংয়ের তালিকা রয়েছে B। আমি প্রতিটি স্ট্রিং এ ফাইল এ নিতে চাই এবং ফাইল বি তে সর্বাধিক অনুরূপ স্ট্রিং সন্ধান করতে চাই

এর জন্য, আমি এমন একটি সরঞ্জাম খুঁজছি যা अस्पष्ट তুলনা সরবরাহ করে।

উদাহরণ স্বরূপ:

$ fuzzy_compare "Some string" "Some string"
100

যেখানে 100 কিছু সাম্য অনুপাত। উদাহরণস্বরূপ লেভেনস্টাইন দূরত্ব

কোন উপযোগ আছে? আমি চাকাটি পুনর্নবীকরণ করতে চাই না।


1
আমি আপনার প্রশ্নটি স্বচ্ছতার উন্নতির জন্য সম্পাদনা করেছি তবে ফাইলএবে প্রতিটি স্ট্রিংকে কেবল ফাইলবিতে নয় এবং কেবল প্রথমটির সাথে তুলনা করার বিষয়ে জিজ্ঞাসা করার জন্য এটি পরিবর্তন করেছি । আমি ধরে নিয়েছিলাম যে আপনি যা বোঝাতে চেয়েছিলেন তবে আমি ভুল হলে দয়া করে আমাকে সংশোধন করুন।
টেরডন


@ মুরু না, এটি কেবল অস্পষ্ট ম্যাচিংয়ের জন্য, ওপি'র স্কোর দরকার।
টেরডন

উত্তর:


23

আমি এই পৃষ্ঠাটি পেয়েছি যা বিভিন্ন ভাষায় লেভেনস্টাইন দূরত্বের অ্যালগরিদমের বাস্তবায়ন সরবরাহ করে। সুতরাং, উদাহরণস্বরূপ ব্যাশে আপনি করতে পারেন:

#!/bin/bash
function levenshtein {
    if [ "$#" -ne "2" ]; then
        echo "Usage: $0 word1 word2" >&2
    elif [ "${#1}" -lt "${#2}" ]; then
        levenshtein "$2" "$1"
    else
        local str1len=$((${#1}))
        local str2len=$((${#2}))
        local d i j
        for i in $(seq 0 $(((str1len+1)*(str2len+1)))); do
            d[i]=0
        done
        for i in $(seq 0 $((str1len))); do
            d[$((i+0*str1len))]=$i
        done
        for j in $(seq 0 $((str2len))); do
            d[$((0+j*(str1len+1)))]=$j
        done

        for j in $(seq 1 $((str2len))); do
            for i in $(seq 1 $((str1len))); do
                [ "${1:i-1:1}" = "${2:j-1:1}" ] && local cost=0 || local cost=1
                local del=$((d[(i-1)+str1len*j]+1))
                local ins=$((d[i+str1len*(j-1)]+1))
                local alt=$((d[(i-1)+str1len*(j-1)]+cost))
                d[i+str1len*j]=$(echo -e "$del\n$ins\n$alt" | sort -n | head -1)
            done
        done
        echo ${d[str1len+str1len*(str2len)]}
    fi
}

while read str1; do
        while read str2; do
                lev=$(levenshtein "$str1" "$str2");
                printf '%s / %s : %s\n' "$str1" "$str2" "$lev"
        done < "$2"
done < "$1"

এটি সংরক্ষণ করুন ~/bin/levenshtein.sh, এটি কার্যকর ( chmod a+x ~/bin/levenshtein.sh) তৈরি করুন এবং আপনার দুটি ফাইলে এটি চালান। উদাহরণ স্বরূপ:

$ cat fileA
foo
zoo
bar
fob
baar
$ cat fileB
foo
loo
baar
bob
gaf
$ a.sh fileA fileB
foo / foo : 0
foo / loo : 1
foo / baar : 4
foo / bob : 2
foo / gaf : 3
zoo / foo : 1
zoo / loo : 1
zoo / baar : 4
zoo / bob : 2
zoo / gaf : 3
bar / foo : 3
bar / loo : 3
bar / baar : 1
bar / bob : 2
bar / gaf : 2
fob / foo : 1
fob / loo : 2
fob / baar : 4
fob / bob : 1
fob / gaf : 3
baar / foo : 4
baar / loo : 4
baar / baar : 0
baar / bob : 3
baar / gaf : 3

এটি কয়েকটি নিদর্শনগুলির জন্য দুর্দান্ত তবে বড় ফাইলগুলির জন্য খুব ধীর পাবে । যদি এটি কোনও সমস্যা হয় তবে অন্য ভাষাগুলিতে প্রয়োগের একটি চেষ্টা করে দেখুন। উদাহরণস্বরূপ পার্ল:

#!/usr/bin/perl 
use List::Util qw(min);

sub levenshtein
{
    my ($str1, $str2) = @_;
    my @ar1 = split //, $str1;
    my @ar2 = split //, $str2;

    my @dist;
    $dist[$_][0] = $_ foreach (0 .. @ar1);
    $dist[0][$_] = $_ foreach (0 .. @ar2);

    foreach my $i (1 .. @ar1) {
        foreach my $j (1 .. @ar2) {
            my $cost = $ar1[$i - 1] eq $ar2[$j - 1] ? 0 : 1;
            $dist[$i][$j] = min(
                            $dist[$i - 1][$j] + 1, 
                            $dist[$i][$j - 1] + 1, 
                            $dist[$i - 1][$j - 1] + $cost
                             );
        }
    }

    return $dist[@ar1][@ar2];
}
open(my $fh1, "$ARGV[0]");
open(my $fh2, "$ARGV[1]");
chomp(my @strings1=<$fh1>);
chomp(my @strings2=<$fh2>);

foreach my $str1 (@strings1) {
    foreach my $str2 (@strings2) {
        my $lev=levenshtein($str1, $str2);
        print "$str1 / $str2 : $lev\n";
    }
}

উপরের মতো, স্ক্রিপ্টটিকে সংরক্ষণ করুন ~/bin/levenshtein.plএবং এটি কার্যকর করতে সক্ষম করুন এবং এটি দুটি ফাইলের সাথে যুক্তি হিসাবে চালনা করুন:

~/bin/levenstein.pl fileA fileB

এমনকি এখানে ব্যবহৃত খুব ছোট ফাইলগুলিতেও পার্ল পদ্ধতির বাশার চেয়ে 10 গুণ দ্রুত:

$ time levenshtein.sh fileA fileB > /dev/null

real    0m0.965s
user    0m0.070s
sys     0m0.057s

$ time levenshtein.pl fileA fileB > /dev/null
real    0m0.011s
user    0m0.010s
sys     0m0.000s

ফলাফল সম্পর্কে আরও কিছু ব্যাখ্যা যুক্ত করতে: উইকিপিডিয়া উদ্ধৃত করে, দুটি শব্দের মধ্যে লেভেনস্টেইন দূরত্ব হ'ল একক অক্ষরে সম্পাদিত (যেমন সন্নিবেশ, মোছা বা বিকল্প) নূন্যতম সংখ্যার এক শব্দের পরিবর্তে অন্য শব্দের পরিবর্তন করতে হবে । তার মানে সংখ্যা যত কম, ম্যাচটি তত ভাল। শূন্যের সংখ্যার অর্থ একটি নিখুঁত ম্যাচ। এছাড়াও নোট করুন যে লেভেনস্টাইন দূরত্ব প্রতিটি চরিত্রকে সমানভাবে পরিচালনা করে, যার অর্থ "foo" এবং "Foo" "foo" এবং "শিয়াল" এর সমান দূরত্বের দিকে পরিচালিত করে।
স্কাই
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.