[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 &lt; $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
+-->
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.