[DOC-CVS] [doc-en] master: Add manual for grapheme_levenshtein function. (#5005)
[email protected] (tekimen via GitHub)
| Newsgroups | php.doc.cvs |
|---|---|
| Message-ID | <[email protected]> |
Author: tekimen (youkidearitai) Committer: GitHub (web-flow) Pusher: lacatoire Date: 2026-08-27T15:25:23+02:00 Commit: https://github.com/php/doc-en/commit/469efd89e78e8d003d7222550f7cdcf4a8f417b1 Raw diff: https://github.com/php/doc-en/commit/469efd89e78e8d003d7222550f7cdcf4a8f417b1.diff Add manual for grapheme_levenshtein function. (#5005) * Add manual for grapheme_levenshtein function. * fix(grapheme-levenshtein): correct and complete documentation - Fix return type: int|false (false on ICU/UTF-8 failure) - Add style.procedural para before methodsynopsis - Add errors section: ValueError for invalid costs, false + intl error for ICU failures - Add changelog section (added in PHP 8.5.0) - Add examples section showing NFC/NFD equivalence vs levenshtein() - Wrap variablelist in para in parameters section - Wrap simplelist in para in seealso section - Use intl.param.grapheme.locale entity for locale parameter - Replace simpara with para in description and returnvalues - Add motivation paragraph: grapheme clusters vs bytes - Fix plural: grapheme clusters (not cluster) - Replace E.g. with For example, and code with literal - Expand cost param descriptions with valid range (must be > 0) - Expand returnvalues to mention false case and intl_get_error_message - Expand seealso: grapheme_strlen, grapheme_substr, similar_text, link --------- Co-authored-by: lcatoire <[email protected]> Changed paths: A reference/intl/grapheme/grapheme-levenshtein.xml Diff: diff --git a/reference/intl/grapheme/grapheme-levenshtein.xml b/reference/intl/grapheme/grapheme-levenshtein.xml new file mode 100644 index 000000000000..3ef5d6ec5bd0 --- /dev/null +++ b/reference/intl/grapheme/grapheme-levenshtein.xml @@ -0,0 +1,217 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- $Revision$ --> +<refentry xml:id="function.grapheme-levenshtein" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink"> + <refnamediv> + <refname>grapheme_levenshtein</refname> + <refpurpose>Calculate Levenshtein distance between two strings in grapheme units</refpurpose> + </refnamediv> + <refsect1 role="description"> + &reftitle.description; + <simpara>&style.procedural;</simpara> + <methodsynopsis> + <type class="union"><type>int</type><type>false</type></type><methodname>grapheme_levenshtein</methodname> + <methodparam><type>string</type><parameter>string1</parameter></methodparam> + <methodparam><type>string</type><parameter>string2</parameter></methodparam> + <methodparam choice="opt"><type>int</type><parameter>insertion_cost</parameter><initializer>1</initializer></methodparam> + <methodparam choice="opt"><type>int</type><parameter>replacement_cost</parameter><initializer>1</initializer></methodparam> + <methodparam choice="opt"><type>int</type><parameter>deletion_cost</parameter><initializer>1</initializer></methodparam> + <methodparam choice="opt"><type>string</type><parameter>locale</parameter><initializer>""</initializer></methodparam> + </methodsynopsis> + <simpara> + The Levenshtein distance is defined as the minimal number of + grapheme clusters that have to be replaced, inserted, or deleted to transform + <parameter>string1</parameter> into <parameter>string2</parameter>. + The complexity of the algorithm is <literal>O(m*n)</literal>, + where <literal>n</literal> and <literal>m</literal> are the + length of <parameter>string1</parameter> and + <parameter>string2</parameter> in grapheme units. + </simpara> + <simpara> + Unlike <function>levenshtein</function>, which operates on bytes, this + function counts Unicode grapheme clusters, so composed and decomposed + forms of the same character (e.g. <literal>U+00E9</literal> and + <literal>U+0065 U+0301</literal>, both representing <literal>é</literal>) + are treated as equivalent and have a distance of zero. + </simpara> + <simpara> + If <parameter>insertion_cost</parameter>, <parameter>replacement_cost</parameter> + and/or <parameter>deletion_cost</parameter> are unequal to <literal>1</literal>, + the algorithm adapts to choose the cheapest transforms. + For example, if <literal>$insertion_cost + $deletion_cost < $replacement_cost</literal>, + no replacements will be done, but rather inserts and deletions instead. + </simpara> + </refsect1> + + <refsect1 role="parameters"> + &reftitle.parameters; + <para> + <variablelist> + <varlistentry> + <term><parameter>string1</parameter></term> + <listitem> + <simpara> + One of the strings being evaluated for Levenshtein distance. + Must be valid UTF-8. + </simpara> + </listitem> + </varlistentry> + <varlistentry> + <term><parameter>string2</parameter></term> + <listitem> + <simpara> + One of the strings being evaluated for Levenshtein distance. + Must be valid UTF-8. + </simpara> + </listitem> + </varlistentry> + <varlistentry> + <term><parameter>insertion_cost</parameter></term> + <listitem> + <simpara> + Defines the cost of insertion. Must be greater than <literal>0</literal>. + </simpara> + </listitem> + </varlistentry> + <varlistentry> + <term><parameter>replacement_cost</parameter></term> + <listitem> + <simpara> + Defines the cost of replacement. Must be greater than <literal>0</literal>. + </simpara> + </listitem> + </varlistentry> + <varlistentry> + <term><parameter>deletion_cost</parameter></term> + <listitem> + <simpara> + Defines the cost of deletion. Must be greater than <literal>0</literal>. + </simpara> + </listitem> + </varlistentry> + <varlistentry> + <term><parameter>locale</parameter></term> + <listitem> + &intl.param.grapheme.locale; + </listitem> + </varlistentry> + </variablelist> + </para> + </refsect1> + + <refsect1 role="returnvalues"> + &reftitle.returnvalues; + <simpara> + Returns the Levenshtein distance between the two strings, measured in + grapheme units, or &false; on failure. Use + <function>intl_get_error_message</function> to retrieve details about + the failure. + </simpara> + </refsect1> + + <refsect1 role="errors"> + &reftitle.errors; + <simpara> + Throws a <exceptionname>ValueError</exceptionname> if + <parameter>insertion_cost</parameter>, <parameter>replacement_cost</parameter>, + or <parameter>deletion_cost</parameter> is less than or equal to + <literal>0</literal>. + </simpara> + <simpara> + Returns &false; and sets an intl error if either input string is not + valid UTF-8, if <parameter>locale</parameter> is not a valid locale + identifier, or if an internal ICU error occurs. + </simpara> + </refsect1> + + <refsect1 role="changelog"> + &reftitle.changelog; + <informaltable> + <tgroup cols="2"> + <thead> + <row> + <entry>&Version;</entry> + <entry>&Description;</entry> + </row> + </thead> + <tbody> + <row> + <entry>8.5.0</entry> + <entry> + This function has been added. + </entry> + </row> + </tbody> + </tgroup> + </informaltable> + </refsect1> + + <refsect1 role="examples"> + &reftitle.examples; + <example> + <title><function>grapheme_levenshtein</function> example</title> + <programlisting role="php"> +<![CDATA[ +<?php + +// Composed form (NFC): U+00E9 LATIN SMALL LETTER E WITH ACUTE +$e_composed = "\u{00E9}"; + +// Decomposed form (NFD): U+0065 + U+0301 (e + combining acute accent) +$e_decomposed = "\u{0065}\u{0301}"; + +// grapheme_levenshtein treats them as the same grapheme cluster +var_dump(grapheme_levenshtein($e_composed, $e_decomposed)); + +// levenshtein() operates on bytes and sees them as different +var_dump(levenshtein($e_composed, $e_decomposed)); + +?> +]]> + </programlisting> + &example.outputs; + <screen> +<![CDATA[ +int(0) +int(3) +]]> + </screen> + </example> + </refsect1> + + <refsect1 role="seealso"> + &reftitle.seealso; + <para> + <simplelist> + <member><function>levenshtein</function></member> + <member><function>grapheme_strlen</function></member> + <member><function>grapheme_substr</function></member> + <member><function>similar_text</function></member> + <member> + <link xlink:href="&uri.unicode.graphemes;"> + Unicode Text Segmentation: Grapheme Cluster Boundaries + </link> + </member> + </simplelist> + </para> + </refsect1> +</refentry> +<!-- Keep this comment at the end of the file +Local variables: +mode: sgml +sgml-omittag:t +sgml-shorttag:t +sgml-minimize-attributes:nil +sgml-always-quote-attributes:t +sgml-indent-step:1 +sgml-indent-data:t +indent-tabs-mode:nil +sgml-parent-document:nil +sgml-default-dtd-file:"~/.phpdoc/manual.ced" +sgml-exposed-tags:nil +sgml-local-catalogs:nil +sgml-local-ecat-files:nil +End: +vim600: syn=xml fen fdm=syntax fdl=2 si +vim: et tw=78 syn=sgml +vi: ts=1 sw=1 +-->