PHP, bir alt içeren değerleri için bir dizi aramak için hızlı yolu nedir?

4 Cevap php

Ben bir web hizmetinden topladık alfabetik olarak sıralanmış sokak isimleri bir dizi var. Bu dizi sunucu tarafında bulunmaktadır.

İstemci tarafında, bir kullanıcı o yaşıyor ve AJAX kısmi sokak adı en yakın maç listesini döndürmek için kullanılan caddenin adını yazarak başlar, artı dizideki sonraki 9 sokak isimleri (liste süre güncellenir o) yazıyor.

Kullanıcı "al" yazdıysanız Örneğin, ben sonuçlar aşağıdaki gibi bir şey olması beklenir:

  • Albany Hwy
  • Albens Vale
  • Alcaston Rd
  • Alex Wood Dr
  • Alice Rd
  • Allawah Ct
  • Allen Rd
  • Alloway Pl
  • Allwood Av
  • Alola St
  • Amanda Dr

Bu da benim bir deneyin:

$matches = array();
for($i = 0; $i < count($streetNames); $i++)
{
  if( (stripos($streetNames, $input) === 0 && count($matches) == 0) || count($matches) < 10 ){
   $matches[] = $streetNames[$i];
  } else {
   break;
  }
}

Başkasının daha hızlı bir yol biliyor mu?

Lütfen dikkat: Bu liste veritabanından nasıl elde edildiğini üzerinde hiçbir kontrole sahip - bu harici bir web hizmeti var.

4 Cevap

Tüm dizeleri bakarak daha hızlı almak için tek yolu bir veri yapısı bu tür bir şey, bir trie için optimize edilmiş olacaktır. Sen webcoder size ne üzerinde kontrole sahip olmayabilir, ancak sunucu üzerinde sonucunu önbelleğe ve sonra bir tray bina ve kullanarak birçok isteklere hizmet için yeniden eğer o kadar hızlı olacaktır.

Sana olan preg_grep() aradığınızı düşünüyorum

Sen giriş metni ile başlayan elemanlar için de arama yapabilirsiniz:

$result = preg_grep('/^$input/', $streetNames);

ya da herhangi bir yerde metin içeren elemanlar için:

$result = preg_grep('/$input/', $streetNames);

ya da sonuna kadar aramayı çapa ama o kadar kullanışlı görünmüyor

Gerçekten daha hızlı olup olmadığını söylemek, ama bu da benim sürümü olamaz.

$input = 'al';
$matches = array_filter($streetNames, create_function('$v','return (stripos($v,'.$input.') !== false ? true : false);'));
$weight = array_map(create_function('$v','return array($v,levenshtein('.$input.',$v));'),$matches);
uasort($weight, create_function('$a,$b', 'if ($a[1] == $b[1]) {return 0;} return ($a[1] < $b[1]) ? -1 : 1;'));
$weight = array_slice($weight, 0, 10);

Bu maçlar ağırlıklı bir listesini oluşturur. Onlar giriş dizesi ve sokak adı arasındaki mesafeye göre sınıflandırılmaktadır. 0 gerçek bir maç temsil eder.

Oluşan bu dizi gibi görünüyor

array (
  0 => 
  array (
    0 => 'Alola St',
    1 => 7,
  ),
  1 => 
  array (
    0 => 'Allen Rd',
    1 => 7,
  )
)

Nerede 0 => cadde ismi ve 1 => levenshtein mesafe