Text

Stemming

Words cut to their stems in 18 languages, so running, runs and run count as one word in a search or a tag cloud.

Version 1.0.0 · 4 functions · 1 crate

#search#text#languages#tags

Functions

What use stemming.qwer gives a program, with the types Quillo sees. To take only some, or under other names: use stem, stem_text from stemming (Quillo 0.6).

stem(word: str, language: str) → stror an error

The stem of one word, in lower case, in language (a two-letter code such as "en", "fr", "de", or a name such as "spanish").

stem_text(text: str, language: str) → listor an error

The stems of the words in text, in order: the text split at anything that is not a letter or digit, in lower case. Up to 1 MB of text.

stem_same(a: str, b: str, language: str) → boolor an error

Whether two words have the same stem: "connected" and "connection" do.

stem_languages() → list

The languages there are, as two-letter codes.

Get it

$ quillo install stemming               # stemming.qwer into this folder$ quillo install stemming --example     # and its example, stemming.qwe

Or with curl:

$ curl -O https://quillolang.org/plugins/files/stemming.qwer$ curl -O https://quillolang.org/plugins/files/stemming.qwe

Then, in your program, all of it or only what you call:

main.qwe
use stemming.qweruse stem, stem_text from stemming      // Quillo 0.6: only these

It uses this crate, which cargo fetches the first time the plugin is built:

[dependencies]
rust-stemmers = "1.2"

Example

stemming.qwe
// A tag cloud that counts "runs", "running" and "run" as one word, in English and French.////   quillo run stemming.qwe      then open http://localhost:8080/clouduse "stemming.qwer"let posts = ["Running shoes for runners", "How I run every morning", "The runner's guide to running in the rain"]route GET /cloud {    let counts = {}    for p in posts {        for s in stem_text(p, "en")? {            counts = set(counts, s, (counts[s] ?? 0) + 1)        }    }    counts}route GET /stem ? { word: str, lang: str = "en" } = { word, stem: stem(word, lang)? }route GET /same = { en: stem_same("connected", "connection", "en")?, fr: stem_same("continuer", "continuation", "fr")?, french: stem_text("Les chanteuses chantaient des chansons", "fr")? }
$ quillo run stemming.qwe$ curl 'localhost:8080/cloud'$ curl 'localhost:8080/stem?word=Laufen&lang=de'

Source

stemming.qwer
//! Words cut to their stems in 18 languages ("running", "runs" and "run" are all "run"), so a search or a tag cloud counts them as one.//! version: 1.0.0//!//! [dependencies]//! rust-stemmers = "1.2"use rust_stemmers::{Algorithm, Stemmer};fn algorithm(language: &str) -> Result<Algorithm, String> {    Ok(match language.trim().to_lowercase().as_str() {        "ar" | "arabic" => Algorithm::Arabic,        "da" | "danish" => Algorithm::Danish,        "nl" | "dutch" => Algorithm::Dutch,        "en" | "english" | "" => Algorithm::English,        "fi" | "finnish" => Algorithm::Finnish,        "fr" | "french" => Algorithm::French,        "de" | "german" => Algorithm::German,        "el" | "greek" => Algorithm::Greek,        "hu" | "hungarian" => Algorithm::Hungarian,        "it" | "italian" => Algorithm::Italian,        "no" | "nb" | "norwegian" => Algorithm::Norwegian,        "pt" | "portuguese" => Algorithm::Portuguese,        "ro" | "romanian" => Algorithm::Romanian,        "ru" | "russian" => Algorithm::Russian,        "es" | "spanish" => Algorithm::Spanish,        "sv" | "swedish" => Algorithm::Swedish,        "ta" | "tamil" => Algorithm::Tamil,        "tr" | "turkish" => Algorithm::Turkish,        other => return Err(format!("no stemmer for {:?}; see stem_languages()", other)),    })}/// The stem of one word, in lower case, in `language` (a two-letter code such as "en", "fr", "de", or a name such as "spanish").pub fn stem(word: &str, language: &str) -> Result<String, String> {    Ok(Stemmer::create(algorithm(language)?).stem(&word.to_lowercase()).into_owned())}/// The stems of the words in `text`, in order: the text split at anything that is not a letter or digit, in lower case. Up to 1 MB of text.pub fn stem_text(text: &str, language: &str) -> Result<Vec<String>, String> {    if text.len() > 1_000_000 {        return Err("text up to 1 MB".into());    }    let s = Stemmer::create(algorithm(language)?);    Ok(text.split(|c: char| !c.is_alphanumeric()).filter(|w| !w.is_empty()).map(|w| s.stem(&w.to_lowercase()).into_owned()).collect())}/// Whether two words have the same stem: "connected" and "connection" do.pub fn stem_same(a: &str, b: &str, language: &str) -> Result<bool, String> {    let s = Stemmer::create(algorithm(language)?);    Ok(s.stem(&a.to_lowercase()) == s.stem(&b.to_lowercase()))}/// The languages there are, as two-letter codes.pub fn stem_languages() -> Vec<String> {    "ar da nl en fi fr de el hu it no pt ro ru es sv ta tr".split(' ').map(String::from).collect()}
Thread
78Useful? Like it, or add to its thread below.

Thread 0 posts

On Stemming: questions, tips, corrections, and code that uses it.

No posts yet. The first one opens the thread.