strsim

    String similarity and distance algorithms for MoonBit (Hamming, Levenshtein, Jaro, Jaro-Winkler, OSA, Damerau-Levenshtein, Sørensen-Dice, LCS)

    string
    similarity
    distance
    levenshtein
    hamming
    jaro
    jaro-winkler
    damerau-levenshtein
    sorensen-dice
    lcs
    Download zip
    Version
    0.2.0
    License
    Apache-2.0
    Last updated
    6 months ago
    Downloads
    56

    #hiroyannnn/strsim

    String similarity algorithms for MoonBit, inspired by strsim-rs.

    #Installation

    moon add hiroyannnn/strsim

    Import in moon.pkg:
    import { "hiroyannnn/strsim" @strsim, }

    #Usage

    #Distance metrics

    ///|
    test "Hamming distance" {
    inspect(try! @strsim.hamming("hamming", "hammers"), content="Ok(3)")
    inspect(try! @strsim.hamming("hamming", "ham"), content="Err(UnequalLength)")
    }

    ///|
    test "Levenshtein distance" {
    inspect(@strsim.levenshtein("kitten", "sitting"), content="3")
    }

    ///|
    test "OSA distance" {
    inspect(@strsim.osa_distance("ac", "cba"), content="3")
    }

    ///|
    test "Damerau-Levenshtein distance" {
    inspect(@strsim.damerau_levenshtein("ac", "cba"), content="2")
    }

    ///|
    test "LCS length" {
    inspect(@strsim.lcs_length("ABCD", "ACBAD"), content="3")
    }

    #Similarity metrics

    ///|
    test "Normalized Levenshtein" {
    let result = @strsim.normalized_levenshtein("kitten", "sitting")
    // 1.0 - 3/7 ≈ 0.571
    assert_true(result > 0.571 && result < 0.572)
    }

    ///|
    test "Jaro similarity" {
    let result = @strsim.jaro("Friedrich Nietzsche", "Jean-Paul Sartre")
    assert_true(result > 0.391 && result < 0.393)
    }

    ///|
    test "Jaro-Winkler similarity" {
    let result = @strsim.jaro_winkler("cheeseburger", "cheese fries")
    assert_true(result > 0.865 && result < 0.867)
    }

    ///|
    test "Sørensen-Dice coefficient" {
    let result = @strsim.sorensen_dice(
    "web applications", "applications of the web",
    )
    assert_true(result > 0.787 && result < 0.789)
    }

    #Enum dispatch

    ///|
    test "distance dispatch" {
    inspect(
    try! @strsim.distance(@strsim.Levenshtein, "kitten", "sitting"),
    content="Ok(3)",
    )
    }

    ///|
    test "similarity dispatch" {
    inspect(@strsim.similarity(@strsim.Jaro, "abc", "abc"), content="1")
    }

    #Algorithm comparison

    #OSA vs Damerau-Levenshtein

    OSA restricts each substring to be edited at most once (not a true metric). Damerau-Levenshtein has no such restriction (true metric, satisfies triangle inequality).

    ///|
    test "OSA vs DL" {
    // "ac" → "cba": OSA needs 3 ops, DL needs only 2
    inspect(@strsim.osa_distance("ac", "cba"), content="3")
    inspect(@strsim.damerau_levenshtein("ac", "cba"), content="2")
    }

    #API reference

    FunctionSignatureDescription
    hamming(String, String) -> Int raise StrsimErrorHamming distance (equal length only)
    levenshtein(String, String) -> IntLevenshtein distance
    normalized_levenshtein(String, String) -> DoubleNormalized Levenshtein (0.0–1.0)
    osa_distance(String, String) -> IntOptimal String Alignment distance
    damerau_levenshtein(String, String) -> IntDamerau-Levenshtein distance (true metric)
    jaro(String, String) -> DoubleJaro similarity
    jaro_winkler(String, String, prefix_weight? : Double) -> DoubleJaro-Winkler similarity (weight clamped to [0.0, 0.25])
    sorensen_dice(String, String) -> DoubleSørensen-Dice coefficient
    lcs_length(String, String) -> IntLongest Common Subsequence length
    distance(DistanceMetric, String, String) -> Int raise StrsimErrorDispatch by enum
    similarity(SimilarityMetric, String, String) -> DoubleDispatch by enum

    #Cross-language comparison

    Algorithmstrsim (MoonBit)strsim-rs (Rust)strsimpy (Python)
    HamminghamminghammingHamming().distance
    LevenshteinlevenshteinlevenshteinLevenshtein().distance
    Normalized Levenshteinnormalized_levenshteinnormalized_levenshteinNormalizedLevenshtein().similarity
    OSAosa_distanceosa_distanceOptimalStringAlignment().distance
    Damerau-Levenshteindamerau_levenshteindamerau_levenshteinDamerauLevenshtein().distance
    JarojarojaroJaro().similarity
    Jaro-Winklerjaro_winklerjaro_winklerJaroWinkler().similarity
    Sørensen-Dicesorensen_dicesorensen_diceSorensenDice().similarity
    LCSlcs_length—LongestCommonSubsequence().distance

    #Acknowledgments

    Algorithm implementations are derived from strsim-rs (MIT License). See NOTICE for details.

    #License

    Apache-2.0

    damerau_levenshtein

    fn damerau_levenshtein(a : String, b : String) -> Int

    distance

    hamming

    fn hamming(a : String, b : String) -> Int raise
    StrsimError

    jaro

    fn jaro(a : String, b : String) -> Double

    jaro_winkler

    fn jaro_winkler(a : String, b : String, prefix_weight? : Double) -> Double

    lcs_length

    fn lcs_length(a : String, b : String) -> Int

    levenshtein

    fn levenshtein(a : String, b : String) -> Int

    normalized_levenshtein

    fn normalized_levenshtein(a : String, b : String) -> Double

    osa_distance

    fn osa_distance(a : String, b : String) -> Int

    similarity

    fn similarity(metric :
    SimilarityMetric
    , a : String, b : String) -> Double

    sorensen_dice

    fn sorensen_dice(a : String, b : String) -> Double

    Source Files