Pull to refresh

T9 своими руками

Reading time4 min
Views3.9K
Привет, хабр!

Набирая смс или просто текст на мобильном телефоне довольно давно хотел сделать Т9 алгоритм самому.

Алгоритм понятен, но все не доходили руки.

Сегодня все же собрался и получилось сделать.

Итак первым делом нужно сформулировать то что хотелось получить.

Задача: Сделать аналог клавиатуры мобильного телефона и набирая цифры — получать список слов.
Ограничение: Особых ограничений не делалось, все таки работа для just for fun, но хочется чтобы было в районе 1 секунды парсинг.
В качестве фичи: Поддержка языков.

В качестве базы слов был взят файл с 26,000 слов.

Теперь сам алгоритм:

Мой алгоритм условно разбит на 2 части.
1 часть — выбирает все слова которые начинаются на одну из букв соответствующей цифре.
То есть для цифры 3 выбираются все слова начинающийся на d,e,f.

2 часть — последовательно проходить по всем числам и отсеивать неподходящие слова.

Поддержка языков:
Думаю всем понятно, что поддержка языков осуществляется заменой букв под цифрами.
По этому реализацию покажу ниже.

В качестве демонстрации используется jquery и эмуляция кнопок телефона.

Посмотреть можно здесь

Теперь сам класс на РНР:
class T9_Exception extends Exception {
}

abstract class T9 {
    protected $wordlist = array(); // слова которые загружаются
    protected $enum = array(); // соответсвие букв и цифр
    protected $mb_support = true; // поддержка мбстринг

    public function mb_support( $status = true ) {
        $this->mb_support = $status;
    }
    public function __construct( $filename=null ) {
        if( $filename )
            $this->load($filename); // грузим файл
    }
    public function load( $filename ) {
        if( file_exists($filename) && is_readable($filename)) {
            $this->wordlist = file($filename);
            //array_walk( $this->wordlist, create_function('&$w', '$w=trim($w);')); // замедляет работу пришлось отключить
            return ;
        }
        throw new T9_Exception("Can not read $filename", 100);

    }
    /**
     * Fetch data from wordlist
     * @param string $input
     * @return array
     */

    public function fetch($input) {
        $compare = array();
        $total = count($this->wordlist);
        for($i=0;$i<$total;$i++) {
            $len = strlen($this->enum[$input[0]]);
            for($j=0;$j<$len;$j++) {
                if( $this->mb_support == true ) {
                    if( mb_strpos($this->wordlist[$i], $this->enum[$input[0]][$j]) === 0)
                        $compare[]=$this->wordlist[$i];
                }
                else {
                    if( strpos($this->wordlist[$i], $this->enum[$input[0]][$j]) === 0)
                        $compare[]=$this->wordlist[$i];
                }

            }
        }
        for($i=1;$i<strlen($input);$i++) {
            $found = false;
            $newcompare = array();
            for($k=0;$k<count($compare);$k++) {
                for($j=0;$j<strlen($this->enum[$input[$i]]);$j++) {
                    $letter = $this->enum[ $input[$i] ][$j];
                    if( $this->mb_support == true) {
                        if( mb_strtolower($compare[$k][$i]) == $letter)
                            $newcompare[] = $compare[$k];
                    }
                    else {
                        if( $compare[$k][$i] == $letter)
                            $newcompare[] = $compare[$k];
                    }



                }
            }
            $compare = $newcompare;
        }
        return $compare;
    }
}


class T9_English extends T9 {

    protected $enum = array(
            0 => '',
            1 => '',
            2 => 'abc',
            3 => 'def',
            4 => 'ghi',
            5 => 'jkl',
            6 => 'mno',
            7 => 'pqrs',
            8 => 'tuv',
            9 => 'wxyz',
    );
}

class T9_Russian extends T9 {
    protected $enum = array(
            0 => '',
            1 => '',
            2 => 'абвг',
            3 => 'деёжз',
            4 => 'ийкл',
            5 => 'мноп',
            6 => 'рсту',
            7 => 'фхцч',
            8 => 'шщъы',
            9 => 'ьэюя',

    );
}


UPD: некоторые байты пропали при выводе, по этому выложил исходник так же по этой ссылке:
http://anton.in.ua/demo/t9/t9.txt

Русский словарь проверять не стал, но судя по алгоритму должно работать так же.

Вот такая небольшая разминка для ума.

Всем спасибо за внимание.
Tags:
Hubs:
+12
Comments13

Articles