arama dizesini ayrıştırmak

2 Cevap php

Ben bir feryat benzer arama dizeleri var:

energy food "olympics 2010" Terrorism OR "government" OR cups NOT transport

ve ben içerik aşağıdaki kümelerden birine ait olmadığını tespit etmek için PHP5 ile ayrıştırmak gerekiyor:

  • AllWords dizi
  • AnyWords dizi
  • NotWords dizi

Bu i kurdunuz kurallar şunlardır:

  1. If it has OR before or after the word or quoted words if belongs to AnyWord.
  2. Bir önce değil kelime veya alıntı kelimeleri varsa o NotWords aittir
  3. If it has 0 or more more spaces before the word or quoted phrase it belongs to AllWords.

Yani sonuçta benzer bir şey olmalıdır:

AllWords: (energy, food, "olympics 2010")
AnyWords: (terrorism, "government", cups)
NotWords: (Transport)

Bu ne için iyi bir yol olurdu?

2 Cevap

Eğer Regex ile bunu yapmak istiyorsanız, ayrıştırma aptal kullanıcı girişi (kullanıcı değil, giriş =)) kıracak unutmayın.

Ben şu ifadelerin denemek istiyorum.

NotWords:

(?<=NOT\s)\b((?!NOT|OR)\w+|"[^"]+")\b

AllWords:

(?<!OR\s)\b((?!NOT|OR)\w+|"[^"]+")\b(?!\s+OR)

AnyWords: Well.. the rest. =) They are not that easy to spot, since I do not know how to put "OR behind it or OR in front of it" into regex. Maybe you could join the results from the three regexes

(?<=OR\s)\b((?!NOT|OR)\w+|"[^"]+")\b(?!\s+OR)
(?<=OR\s)\b((?!NOT|OR)\w+|"[^"]+")\b(?=\s+OR)
(?<!OR\s)\b((?!NOT|OR)\w+|"[^"]+")\b(?=\s+OR)

Sorunlar: Bu değiştirici kelime ve ifadeler arasında tam olarak bir boşluk gerektirir. PHP sadece düzeltmeleri uzunluğu ifadeler için geriye ilerleme destekler, bu yüzden etrafında hiçbir şekilde görmek, üzgünüm. Sadece \b(\w+|"[^"]+")\b girişini bölmek için kullanmak, ve elle çıkan dizi ayrıştırmak.

Bu test ilk odaklı yaklaşımı bir çözüme varmak nasıl yardımcı mükemmel bir örnektir. O çok iyi biri olmayabilir, ancak yazılı olan testler güvenle Refactor ve anında mevcut testlerin herhangi kırmak görmek için izin verir. Neyse, sizin gibi birkaç testleri kurmak olabilir:

public function setUp () {
  $this->searchParser = new App_Search_Parser();
}

public function testSingleWordParsesToAllWords () {
  $this->searchParser->parse('Transport');
  $this->assertEquals(
     $this->searchParser->getAllWords(), 
     array('Transport')
  );
  $this->assertEquals($this->searchParser->getNotWords(), array());
  $this->assertEquals($this->searchParser->getAnyWords());
}

public function testParseOfCombinedSearchString () {
   $query = 'energy food "olympics 2010" Terrorism ' . 
            'OR "government" OR cups NOT transport';
   $this->searchParser->parse($query);

  $this->assertEquals(
     $this->searchParser->getAllWords(), 
     array('energy', 'food', 'olympics 2010')
  );
  $this->assertEquals(
     $this->searchParser->getNotWords(), 
     array('Transport')
  );
  $this->assertEquals(
     $this->searchParser->getAnyWords(),
     array( 'terrorism', 'government', 'cups')
  );
}

Diğer iyi testler şunlardır:

  • testParseTwoWords
  • testParseTwoWordsWithOr
  • testParseSimpleWithNot
  • testParseInvalid
    • Burada geçersiz giriş neye benzediğini ve bunu nasıl yorumlamak, yani karar vermek zorunda:
    • 'Taşıma DEĞİL': Transport içeren ya da o da en az bir arama terimini vardır kullanıcıyı bilgilendirmek değil bir şey için ara?
    • 'OR enerji': Bir combinator başlamak için Tamam mı?
    • 'Gıda OLMASIN enerji': Bu demek "yiyecek ya da enerjiyi içermiyor şey aramak", ya da "gıda ve enerji değil, araştırın" demek, ya da hiçbir şey demek değil mi? (Yani atış istisna, return false ya da etajer)
  • testParseEmpty

Then, write the tests one by one, and write a simple solution that passes the test. Then refactor and make it right, and run again to see that you still pass the test. Once a test passes and the code is refactored, then write the next test and repeat the procedure. Add more tests as you find special cases and refactor the code so that it passes all tests. If you break a test, back-up and re-write the code (not the test!) such that it passes.

Eğer bu sorunu çözebilir nasıl gelince, preg_match, strtok içine bakmak ya da gitmek gibi belirteçleri kadar ekleyerek dize yoluyla sadece döngü güveniyor.