तुलना के स्ट्रिंग्स जावास्क्रिप्ट रिटर्न% की तुलना करें


87

मैं एक जावास्क्रिप्ट फ़ंक्शन की तलाश कर रहा हूं जो दो तारों की तुलना कर सकता है और इस संभावना को वापस कर सकता है कि वे एक जैसे हैं। मैंने साउंडटेक्स को देखा है, लेकिन यह बहु-शब्द स्ट्रिंग्स या गैर-नामों के लिए बहुत अच्छा नहीं है। मैं एक समारोह की तरह देख रहा हूँ:

function compare(strA,strB){

}

compare("Apples","apple") = Some X Percentage.

फ़ंक्शन सभी प्रकार के स्ट्रिंग्स के साथ काम करेगा, जिसमें संख्याएं, बहु-शब्द मान और नाम शामिल हैं। शायद वहाँ एक सरल एल्गोरिथ्म मैं उपयोग कर सकता है?

Ultimately none of these served my purpose so I used this:

 function compare(c, u) {
        var incept = false;
        var ca = c.split(",");
        u = clean(u);
        //ca = correct answer array (Collection of all correct answer)
        //caa = a single correct answer word array (collection of words of a single correct answer)
        //u = array of user answer words cleaned using custom clean function
        for (var z = 0; z < ca.length; z++) {
            caa = $.trim(ca[z]).split(" ");
            var pc = 0;
            for (var x = 0; x < caa.length; x++) {
                for (var y = 0; y < u.length; y++) {
                    if (soundex(u[y]) != null && soundex(caa[x]) != null) {
                        if (soundex(u[y]) == soundex(caa[x])) {
                            pc = pc + 1;
                        }
                    }
                    else {
                        if (u[y].indexOf(caa[x]) > -1) {
                            pc = pc + 1;
                        }
                    }
                }
            }
            if ((pc / caa.length) > 0.5) {
                return true;
            }
        }
        return false;
    }

    // create object listing the SOUNDEX values for each letter
    // -1 indicates that the letter is not coded, but is used for coding
    //  0 indicates that the letter is omitted for modern census archives
    //                              but acts like -1 for older census archives
    //  1 is for BFPV
    //  2 is for CGJKQSXZ
    //  3 is for DT
    //  4 is for L
    //  5 is for MN my home state
    //  6 is for R
    function makesoundex() {
        this.a = -1
        this.b = 1
        this.c = 2
        this.d = 3
        this.e = -1
        this.f = 1
        this.g = 2
        this.h = 0
        this.i = -1
        this.j = 2
        this.k = 2
        this.l = 4
        this.m = 5
        this.n = 5
        this.o = -1
        this.p = 1
        this.q = 2
        this.r = 6
        this.s = 2
        this.t = 3
        this.u = -1
        this.v = 1
        this.w = 0
        this.x = 2
        this.y = -1
        this.z = 2
    }

    var sndx = new makesoundex()

    // check to see that the input is valid
    function isSurname(name) {
        if (name == "" || name == null) {
            return false
        } else {
            for (var i = 0; i < name.length; i++) {
                var letter = name.charAt(i)
                if (!(letter >= 'a' && letter <= 'z' || letter >= 'A' && letter <= 'Z')) {
                    return false
                }
            }
        }
        return true
    }

    // Collapse out directly adjacent sounds
    // 1. Assume that surname.length>=1
    // 2. Assume that surname contains only lowercase letters
    function collapse(surname) {
        if (surname.length == 1) {
            return surname
        }
        var right = collapse(surname.substring(1, surname.length))
        if (sndx[surname.charAt(0)] == sndx[right.charAt(0)]) {
            return surname.charAt(0) + right.substring(1, right.length)
        }
        return surname.charAt(0) + right
    }

    // Collapse out directly adjacent sounds using the new National Archives method
    // 1. Assume that surname.length>=1
    // 2. Assume that surname contains only lowercase letters
    // 3. H and W are completely ignored
    function omit(surname) {
        if (surname.length == 1) {
            return surname
        }
        var right = omit(surname.substring(1, surname.length))
        if (!sndx[right.charAt(0)]) {
            return surname.charAt(0) + right.substring(1, right.length)
        }
        return surname.charAt(0) + right
    }

    // Output the coded sequence
    function output_sequence(seq) {
        var output = seq.charAt(0).toUpperCase() // Retain first letter
        output += "-" // Separate letter with a dash
        var stage2 = seq.substring(1, seq.length)
        var count = 0
        for (var i = 0; i < stage2.length && count < 3; i++) {
            if (sndx[stage2.charAt(i)] > 0) {
                output += sndx[stage2.charAt(i)]
                count++
            }
        }
        for (; count < 3; count++) {
            output += "0"
        }
        return output
    }

    // Compute the SOUNDEX code for the surname
    function soundex(value) {
        if (!isSurname(value)) {
            return null
        }
        var stage1 = collapse(value.toLowerCase())
        //form.result.value=output_sequence(stage1);

        var stage1 = omit(value.toLowerCase())
        var stage2 = collapse(stage1)
        return output_sequence(stage2);

    }

    function clean(u) {
        var u = u.replace(/\,/g, "");
        u = u.toLowerCase().split(" ");
        var cw = ["ARRAY OF WORDS TO BE EXCLUDED FROM COMPARISON"];
        var n = [];
        for (var y = 0; y < u.length; y++) {
            var test = false;
            for (var z = 0; z < cw.length; z++) {
                if (u[y] != "" && u[y] != cw[z]) {
                    test = true;
                    break;
                }
            }
            if (test) {
    //Don't use & or $ in comparison
                var val = u[y].replace("$", "").replace("&", "");
                n.push(val);
            }
        }
        return n;
    }


मैं इसे बाहर का परीक्षण कर रहा हूं, फिर भी एकदम सही खोजने में परेशानी हो रही है इनको तोड़ने वाला क्लासिक उदाहरण। प्रश्न कहो "पहले दो राष्ट्रपति क्या हैं?" और कोई व्यक्ति "एडम्स और वॉशिंगटन" का जवाब देता है। "जॉर्ज वॉशिंगटन जॉन एडम्स" की तुलना लगभग 50% होनी चाहिए।
ब्रैड रुडरमैन

oof, jQuery पर निर्भर करता है?
शॉन व्हेनरी

जवाबों:


138

यहाँ एक जवाब है, जो लेवेंसहाइट दूरी पर आधारित है। https://en.wikipedia.org/wiki/Levenshtein_distance

function similarity(s1, s2) {
  var longer = s1;
  var shorter = s2;
  if (s1.length < s2.length) {
    longer = s2;
    shorter = s1;
  }
  var longerLength = longer.length;
  if (longerLength == 0) {
    return 1.0;
  }
  return (longerLength - editDistance(longer, shorter)) / parseFloat(longerLength);
}

संपादित दूरी की गणना के लिए

function editDistance(s1, s2) {
  s1 = s1.toLowerCase();
  s2 = s2.toLowerCase();

  var costs = new Array();
  for (var i = 0; i <= s1.length; i++) {
    var lastValue = i;
    for (var j = 0; j <= s2.length; j++) {
      if (i == 0)
        costs[j] = j;
      else {
        if (j > 0) {
          var newValue = costs[j - 1];
          if (s1.charAt(i - 1) != s2.charAt(j - 1))
            newValue = Math.min(Math.min(newValue, lastValue),
              costs[j]) + 1;
          costs[j - 1] = lastValue;
          lastValue = newValue;
        }
      }
    }
    if (i > 0)
      costs[s2.length] = lastValue;
  }
  return costs[s2.length];
}

प्रयोग

similarity('Stack Overflow','Stack Ovrflw')

रिटर्न 0.8571428571428571


आप इसके साथ नीचे खेल सकते हैं:


कई शब्दों के लिए एक सुधार: var समानता 2 = फ़ंक्शन (s1, s2) {var विभाजित 1 = s1.split (''); var विभाजन 2 = s2.split (''); var योग = 0; var अधिकतम = 0; var अस्थायी = 0; के लिए (var i = 0; मैं <स्प्लिट 1.length; i ++) {अधिकतम = 0; के लिए (var j = 0; j <विभाजित 2.length; j ++) {अस्थायी = समानता (विभाजित 1 [i], विभाजित 2 [जे]); अगर (अधिकतम <अस्थायी) अधिकतम = अस्थायी; } कंसोल.लॉग (अधिकतम); योग + = अधिकतम / विभाजन १. गति; } वापसी राशि; };
infinito84

@ ओवरऑर्ड 1234 इस तरह से स्ट्रिंग के लिए उपरोक्त विधि काम करता है: 9e27db9ff6eea70821c02b4457cbc6b7b8eb8e12a64f46c192c3c5a1bb1519acd101193dac157c6233d773d773&c=3444
हाइपरफेकब

यह इसके साथ जुड़े सिमेंटिक के बिना तार के साथ काम करता है। कृपया कोशिश करें और इन-लाइन कोड स्निपेट (डेविड के लिए धन्यवाद) चलाएं। जब मैं उपरोक्त तार इनपुट करता हूं तो मुझे 0.17857142857142858 की समानता मिलती है।
overlord1234

@hyperfkcb वह संपादन दूरी एल्गोरिथ्म को लागू कर रहा है, जो गिनता है कि कितने वर्ण गलत स्थिति में हैं (अधिक या कम), इसलिए प्रतिशत की गणना के लिए वह अधिक संभव संपादित दूरी मान (लंबी अवधि) और कर रहा है (longLength - editDistance) / longerLength।
infinito84

हालांकि, यह लंबे तारों के लिए बहुत धीमा है।
१ming

14

यहाँ एक बहुत ही सरल कार्य है जो एक तुलना करता है और समकक्षता के आधार पर प्रतिशत देता है। हालांकि यह सभी संभावित परिदृश्यों के लिए परीक्षण नहीं किया गया है, यह आपको आरंभ करने में मदद कर सकता है।

function similar(a,b) {
    var equivalency = 0;
    var minLength = (a.length > b.length) ? b.length : a.length;    
    var maxLength = (a.length < b.length) ? b.length : a.length;    
    for(var i = 0; i < minLength; i++) {
        if(a[i] == b[i]) {
            equivalency++;
        }
    }
    

    var weight = equivalency / maxLength;
    return (weight * 100) + "%";
}
alert(similar("test","tes"));   // 75%
alert(similar("test","test"));  // 100%
alert(similar("test","testt")); // 80%
alert(similar("test","tess"));  // 75%

9
इसके साथ समस्या यह है कि "एटेस्ट" और "टेस्ट" रिटर्न 0% है, जिसे हम जानते हैं कि यह सच नहीं है।
पर्सिसेउसर

8

स्ट्रिंग समानता के लिए इस पुस्तकालय का उपयोग करना मेरे लिए एक आकर्षण की तरह काम करता है!

यहाँ उदाहरण है -

var similarity = stringSimilarity.compareTwoStrings("Apples","apple");    // => 0.88

6
यह महान है, सिवाय इसके कि स्ट्रिंगसिलेरिटी में एक आश्रितता है जिसे लॉश कहा जाता है जिसमें 1,000 से अधिक फाइलें हैं जो आपके प्रोजेक्ट में डाली जा रही हैं ताकि आप स्ट्रिंग समानता प्राप्त कर सकें।
ग्राम्प्रेकटन

2
हाँ, यह स्थानीय रूप से पैकेज को जोड़ने के दौरान होता है। लेकिन इसके बजाय, हम कम बंडल आकार के लिए CDN का उपयोग कर सकते हैं । यहाँ CDN लिंक दिए गए हैं - jsdelivr.com/package/npm/lodash - jsdelivr.com/package/npm/string-similarity
तुषार वाल्ज़डे

2
वे lodash सहित अधिकांश निर्भरता, को हटा दिया है
Lovenkrands

7

सिर्फ एक मैंने जल्दी से लिखा है कि आपके उद्देश्यों के लिए काफी अच्छा हो सकता है:

function Compare(strA,strB){
    for(var result = 0, i = strA.length; i--;){
        if(typeof strB[i] == 'undefined' || strA[i] == strB[i]);
        else if(strA[i].toLowerCase() == strB[i].toLowerCase())
            result++;
        else
            result += 4;
    }
    return 1 - (result + 4*Math.abs(strA.length - strB.length))/(2*(strA.length+strB.length));
}

यह उन वर्णों का वजन करता है जो एक ही तरह के होते हैं, लेकिन अलग-अलग स्थिति 1 तिमाही में उन पात्रों के रूप में भारी होते हैं जो पूरी तरह से अलग या गायब होते हैं। यह 0 और 1 के बीच एक संख्या देता है, 1 का अर्थ है कि तार समान हैं। 0 का मतलब है कि उनमें कोई समानता नहीं है। उदाहरण:

Compare("Apple", "Apple")    // 1
Compare("Apples", "Apple")   // 0.8181818181818181
Compare("Apples", "apple")   // 0.7727272727272727
Compare("a", "A")            // 0.75
Compare("Apples", "appppp")  // 0.45833333333333337
Compare("a", "b")            // 0

6
इतना सटीक नहीं: तुलना करें ("Apple", "zApple") = 0.07, जबकि तुलना करें ("Apple", "Applez") = 0.84
Kousha

3
@ कुशा, यह स्थिति है। "Apple" और "zApple" में केवल एक अक्षर समान (दूसरा p) है।
पॉल

2
@Paulpro Apple और zApple में सामान्य रूप से पाँच अक्षर हैं। यह आपके कार्यान्वयन की गलती है। Apple, zApple, Applez समान हैं।
कुषा

2
@Kousha, zApple इस एल्गोरिथ्म के अनुसार समान नहीं है, क्योंकि यह स्थिति है। यह एल्गोरिथ्म को गलत नहीं बनाता है।
पॉल

8
@Paulpro: जो आपके एल्गोरिथ्म को गलत नहीं बनाता है, लेकिन यह इस प्रश्न के लिए एक खराब उत्तर देता है ...
मार्कोस

6

PHP.js लाइब्रेरीsimilar_text से फ़ंक्शन के बारे में कैसे ?

यह उसी नाम के साथ PHP फ़ंक्शन पर आधारित है ।

function similar_text (first, second) {
    // Calculates the similarity between two strings  
    // discuss at: http://phpjs.org/functions/similar_text

    if (first === null || second === null || typeof first === 'undefined' || typeof second === 'undefined') {
        return 0;
    }

    first += '';
    second += '';

    var pos1 = 0,
        pos2 = 0,
        max = 0,
        firstLength = first.length,
        secondLength = second.length,
        p, q, l, sum;

    max = 0;

    for (p = 0; p < firstLength; p++) {
        for (q = 0; q < secondLength; q++) {
            for (l = 0;
            (p + l < firstLength) && (q + l < secondLength) && (first.charAt(p + l) === second.charAt(q + l)); l++);
            if (l > max) {
                max = l;
                pos1 = p;
                pos2 = q;
            }
        }
    }

    sum = max;

    if (sum) {
        if (pos1 && pos2) {
            sum += this.similar_text(first.substr(0, pos2), second.substr(0, pos2));
        }

        if ((pos1 + max < firstLength) && (pos2 + max < secondLength)) {
            sum += this.similar_text(first.substr(pos1 + max, firstLength - pos1 - max), second.substr(pos2 + max, secondLength - pos2 - max));
        }
    }

    return sum;
}

1
क्या समानता मैचिंग चरित्र के आधार पर लौटती है? यह समानता का मूल्यांकन कैसे करता है
हाइपरफेकबी

3

दो तारों के बीच समानता की डिग्री खोजने के लिए; हम एक या दो से अधिक तरीकों का उपयोग कर सकते हैं, लेकिन मैं ज्यादातर ' डाइस के गुणांक ' के उपयोग के लिए इच्छुक हूं । कौनसा अच्छा है! मेरे ज्ञान में ' लेवेन्सहाइटिन दूरी ' का उपयोग करने से

Npm से इस ' स्ट्रिंग-समानता ' पैकेज का उपयोग करके आप ऊपर बताए गए काम पर काम कर पाएंगे।

कुछ आसान उपयोग उदाहरण हैं

var stringSimilarity = require('string-similarity');

var similarity = stringSimilarity.compareTwoStrings('healed', 'sealed'); 

var matches = stringSimilarity.findBestMatch('healed', ['edward', 'sealed', 'theatre']);

अधिक जानकारी के लिए कृपया ऊपर दिए गए लिंक पर जाएं। धन्यवाद।


1
किसी समाधान का लिंक स्वागत योग्य है, लेकिन कृपया सुनिश्चित करें कि आपका उत्तर इसके बिना उपयोगी है: लिंक के चारों ओर संदर्भ जोड़ें ताकि आपके साथी उपयोगकर्ताओं को यह पता चले कि यह क्या है और यह क्यों है, तो पृष्ठ के सबसे प्रासंगिक हिस्से को उद्धृत करें ' मामले में लक्ष्य पृष्ठ अनुपलब्ध होने पर पुनः लिंक करना। ऐसे लिंक जो किसी लिंक से बहुत कम हैं उन्हें हटाया जा सकता है
डेविड बक

1

fuzzyset - जावास्क्रिप्ट के लिए एक फ़ज़ी स्ट्रिंग सेट। फ़ज़ीसेट एक डेटा संरचना है, जो संभावित गलतफहमी और अनुमानित स्ट्रिंग मिलान का निर्धारण करने के लिए डेटा के खिलाफ पूर्ण खोज के लिए कुछ प्रकार का कार्य करता है। ध्यान दें कि यह एक अजगर पुस्तकालय का एक जावास्क्रिप्ट पोर्ट है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.