Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
215 changes: 215 additions & 0 deletions reference/intl/grapheme/grapheme-levenshtein.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- EN-Revision: 469efd89e78e8d003d7222550f7cdcf4a8f417b1 Maintainer: shein Status: ready -->
<!-- Reviewed: no -->
<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>Вычисляет расстояние Левенштейна между двумя строками в графемных кластерах</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>
Расстояние Левенштейна определяется как минимум графемных кластеров,
которые требуется заменить, вставить или удалить, чтобы преобразовать строку
<parameter>string1</parameter> в строку <parameter>string2</parameter>.
Сложность алгоритма — <literal>O(m*n)</literal>, где <literal>n</literal>
и <literal>m</literal> — длины строк <parameter>string1</parameter>
и <parameter>string2</parameter> в графемных кластерах.
</simpara>
<simpara>
В отличие от функции <function>levenshtein</function>, которая работает с байтами,
функция считает графемные кластеры Юникода,
поэтому составную и разложенную формы одного и того же символа,
например <literal>U+00E9</literal> и <literal>U+0065 U+0301</literal>,
каждая из которых представляет символ <literal>é</literal>,
функция считает эквивалентными, а расстояние между формами — нулевым.
</simpara>
<simpara>
Алгоритм подстроится и выберет самые дешёвые преобразования,
если значения параметров <parameter>insertion_cost</parameter>,
<parameter>replacement_cost</parameter> или <parameter>deletion_cost</parameter>
не равны <literal>1</literal>.
Например, при истинности выражения <literal>$insertion_cost + $deletion_cost &lt; $replacement_cost</literal>
вместо замен выполняются вставки и удаления.
</simpara>
</refsect1>

<refsect1 role="parameters">
&reftitle.parameters;
<para>
<variablelist>
<varlistentry>
<term><parameter>string1</parameter></term>
<listitem>
<simpara>
Строка в кодировке UTF-8 для вычисления расстояния Левенштейна.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>string2</parameter></term>
<listitem>
<simpara>
Строка в кодировке UTF-8 для вычисления расстояния Левенштейна.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>insertion_cost</parameter></term>
<listitem>
<simpara>
Стоимость вставки — значение больше <literal>0</literal>.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>replacement_cost</parameter></term>
<listitem>
<simpara>
Стоимость замены — значение больше <literal>0</literal>.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>deletion_cost</parameter></term>
<listitem>
<simpara>
Стоимость удаления — значение больше <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>
Функция возвращает расстояние Левенштейна между двумя строками в графемных
кластерах или &false;, если возникла ошибка. Подробности об ошибке возвращает
функция <function>intl_get_error_message</function>.
</simpara>
</refsect1>

<refsect1 role="errors">
&reftitle.errors;
<simpara>
Функция выбрасывает ошибку <exceptionname>ValueError</exceptionname>,
если значение параметра <parameter>insertion_cost</parameter>,
<parameter>replacement_cost</parameter> или <parameter>deletion_cost</parameter>
меньше или равно <literal>0</literal>.
</simpara>
<simpara>
Функция возвращает &false; и устанавливает ошибку модуля Intl,
если хотя бы одна входная строка не соответствует кодировке UTF-8,
в параметр <parameter>locale</parameter> передали недопустимый идентификатор локали
или возникла внутренняя ошибка библиотеки ICU.
</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>
Функцию добавили в модуль.
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</refsect1>

<refsect1 role="examples">
&reftitle.examples;
<example>
<title>Пример вычисления расстояния Левенштейна функцией <function>grapheme_levenshtein</function></title>
<programlisting role="php">
<![CDATA[
<?php

// Составная форма (NFC): U+00E9 LATIN SMALL LETTER E WITH ACUTE
$e_composed = "\u{00E9}";

// Разложенная форма (NFD): U+0065 + U+0301 (e + комбинируемый акут)
$e_decomposed = "\u{0065}\u{0301}";

// Функция grapheme_levenshtein() считает обе формы как единый графемный кластер
var_dump(grapheme_levenshtein($e_composed, $e_decomposed));

// Функция levenshtein() работает с байтами и видит разные байтовые последовательности
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;">
Сегментация текста в Юникоде: Границы графемных кластеров
</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
-->
Loading