Re: Нечеткое сравнение слов.
От: F3V  
Дата: 17.10.25 13:37
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Есть набор из названий брендов (озвучено — порядка миллиона).

V>Есть входная строка, например "планшет Samsung"

V>Необходимо без ИИ сопоставить бренд из словаря этой строке.


V>Затем даётся дополнительное ТЗ — необходимо сделать поиск нечётким, т.е. с возможными опечатками.


Взял PEG.js:

В словаре слово: samsung
Возможные опечатки: u->a | a->u | u->y | y->u
Входные строки вида: samsung samsyng sumsyng

  Грамматика
/*
В словаре слово: samsung
Возможные опечатки: u->a | a->u | u->y | y->u
Входные строки вида: samsung samsyng sumsyng
*/
{
  options.dictionary = {};
  options.typo = {};
  var add = (dictionary, text)=>{
      var obj = dictionary;
    (text+'.').split('').forEach(_=>{
        var next = obj[_];
        obj = next = next?next:(obj[_]={});
    });
  }
  add(options.dictionary, "samsung");
  add(options.typo, "ua");
  add(options.typo, "au");
  add(options.typo, "uy");
  add(options.typo, "yu");
  console.log(options.typo);
  
  options.next = (ctx,sym)=>{
    console.log('next:',JSON.stringify(ctx),sym);
    if (!ctx.tss.length) return false;
    var addts = [];
    ctx.tss = ctx.tss.flatMap(_=>{
        if (!_.ts) { return []; }
        var nnts = {ts:_.ts,res:_.res,orig:_.orig,typos:_.typos};
        _.ts = _.ts[sym];
        _.res = _.ts ? _.res + sym : '';
        _.orig = _.ts ? _.orig + sym : '';
        {
            var tsym = options.typo[sym];
            if (tsym != undefined) {
                var variants = Object.keys(tsym)
                variants.forEach(v=>{
                  var nts = {ts:nnts.ts,res:nnts.res,orig:nnts.orig,typos:nnts.typos};
                  nts.ts = nts.ts[v];
                  nts.orig = nts.ts ? nts.orig + sym : '';
                  nts.res = nts.ts ? nts.res + v : '';
                  ++nts.typos;
                  if (nts.ts) {
                      addts.push(nts);
                  }
                });
            }
        }
        return _.ts ? _ : [];
    }).concat(addts);
    return !!ctx.tss.length;
  }
  
  options.valid = (ctx)=>{
    if (!ctx.tss.length) return false;
    ctx.tss = ctx.tss.map(_=>undefined != _.ts['.']?_:null).filter(_=>_);
    return !!ctx.tss.length;
  }
}

words = (word _)+

ctx = &(.) {return {tss:[{ts:options.dictionary, res:'',orig:'',typos:0}]};}

word = ctx:ctx word:(s:[a-z] &{return options.next(ctx,s);} {return s;})+ &{return options.valid(ctx);} { return ctx;}

_ = [ \t\r\n]*


Нужно подготовить два словаря: брендов и опечаток.
Миллион для таких словарей не много, должно потянуть.

По идее, работает достаточно быстро.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.