JSFiddle - React, Tailwind, and code Playground
by mgibsonbr
HTML
<ul>
</ul>
<input />
<button>buscar</button>
<button>arvore</button>
<button>\xe1rvore</button>
<button>a\u0301rvore</button>
<br/>
<label><input type="checkbox" checked />Ignorar maiúsculas/minúsculas</label>
<label title="Se checado, acentos no termo de busca casam com palavras não acentuadas também. Se deixado sem, acentos no termo de busca só casam com letras igualmente acentuadas (embora as mesmas podem estar representadas de uma forma diferente)."><input type="checkbox" checked disabled />Ignorar acento no termo de busca</label>
<hr/>
Tempo de preparo: <span>∞</span> µs (só faz sentido se a lista for grande)
<br/>
Tempo médio de busca: <span>∞</span> µs (<span>0</span> casos)
CSS
.achou {
background: lightgray;
}
JavaScript
function preparar(lista) {
return lista.map(prepararTermoBusca);
}
function prepararTermoBusca(str) {
str = str.replace(/[ÀÁÂÃÄÅ]/,"A");
str = str.replace(/[àáâãäå]/,"a");
str = str.replace(/[ÈÉÊË]/,"E");
str = str.replace(/[Ç]/,"C");
str = str.replace(/[ç]/,"c");
// o resto
str = str.replace(/[èéêë]/,"e");
str = str.replace(/[ÌÍÎÏ]/,"I");
str = str.replace(/[ìíîï]/,"i");
str = str.replace(/[ÒÓÔÖÕ]/,"O");
str = str.replace(/[òóôöõ]/,"o");
str = str.replace(/[ÙÚÛÜ]/,"U");
str = str.replace(/[ùúûü]/,"u");
str = str.replace(/[Ñ]/,"N");
str = str.replace(/[ñ]/,"n");
return str.replace(/[^a-z0-9]/gi,'');
}
function comparar(elementoLista, termoBusca, ignoreCase) {
if ( ignoreCase )
return elementoLista.toLocaleLowerCase() == termoBusca.toLocaleLowerCase();
return elementoLista == termoBusca;
}
////// Teste //////
var lista = [
"acentuacao",
'arvore',
'\xe1rvore',
'a\u0301rvore',
"divagacão",
"programaçao",
"taxação"
];
var listaPreparada = null;
for ( var i = 0 ; i < lista.length ; i++ )
$("ul").append('<li>' + lista[i] + '</li>');
var buscas = [];
$("button:eq(0)").click(function() {
var termoBusca = $("input:eq(0)").val();
$("li").removeClass("achou");
if ( !listaPreparada ) {
var now = new Date();
var repetir = 1000;
while ( repetir-- > 0 )
listaPreparada = preparar(lista);
$("span:eq(0)").text(((new Date() - now)/1).toFixed(3));
}
var ignoreCase = $("input:eq(1)").prop("checked");
var now = new Date();
var repetir = 10000;
while ( repetir-- > 0 ) {
var termoPreparado = prepararTermoBusca(termoBusca);
for ( var i = 0 ; i < listaPreparada.length ; i++ )
if ( comparar(listaPreparada[i], termoPreparado, ignoreCase) )
$("li").eq(i).addClass("achou");
}
buscas.push((new Date() - now)/lista.length/10);
...