Vraag Hoe controleer ik of een string een specifiek woord bevat?


Overwegen:

$a = 'How are you?';

if ($a contains 'are')
    echo 'true';

Stel dat ik de bovenstaande code heb, wat is de juiste manier om de verklaring te schrijven if ($a contains 'are')?


2668


oorsprong


antwoorden:


U kunt de strpos() functie die wordt gebruikt om het voorkomen van één string binnen een andere te vinden:

$a = 'How are you?';

if (strpos($a, 'are') !== false) {
    echo 'true';
}

Merk op dat het gebruik van !== false is opzettelijk; strpos() retourneert ofwel de offset waarmee de naaldstreng begint in de hooibergstring of de boolean false als de naald niet is gevonden. Omdat 0 een geldige offset is en 0 "falsey", kunnen we geen eenvoudigere constructies gebruiken zoals !strpos($a, 'are').


5436



Je zou reguliere expressies kunnen gebruiken, het is beter voor woordafstemming in vergelijking met strpos, zoals vermeld door andere gebruikers, het zal ook waar terugkeren voor tekenreeksen zoals tarief, zorg, staren enz. Dit kan eenvoudig worden voorkomen in de reguliere expressie door woordgrenzen te gebruiken.

Een eenvoudige match voor zou er ongeveer zo uit kunnen zien:

$a = 'How are you?';

if (preg_match('/\bare\b/',$a))
    echo 'true';

Aan de performance kant, strpos is ongeveer drie keer sneller en in gedachten, toen ik een miljoen vergelijkingen tegelijk deed, duurde het 1,5 seconden om te voltooien en voor strpos duurde het 0,5 seconde.


450



Hier is een kleine utility-functie die handig is in situaties zoals deze

// returns true if $needle is a substring of $haystack
function contains($needle, $haystack)
{
    return strpos($haystack, $needle) !== false;
}

195



Hoewel de meeste van deze antwoorden u vertellen of een subtekenreeks in uw reeks voorkomt, is dat meestal niet wat u zoekt als u op zoek bent naar een bepaalde woord, en niet een substring.

Wat is het verschil? Substrings kunnen met andere woorden verschijnen:

  • De "zijn" aan het begin van "gebied"
  • De "zijn" aan het einde van "haas"
  • De "zijn" in het midden van "tarieven"

Een manier om dit te verminderen zou zijn om een ​​reguliere expressie te gebruiken in combinatie met woordgrenzen (\b):

function containsWord($str, $word)
{
    return !!preg_match('#\\b' . preg_quote($word, '#') . '\\b#i', $str);
}

Deze methode heeft niet dezelfde foutpositieven als hierboven vermeld, maar er zijn wel enkele eigen randgevallen. Woordgrenzen komen overeen op niet-woordtekens (\W), die alles zullen zijn wat niet is a-z, A-Z, 0-9of _. Dat betekent dat cijfers en onderstrepingstekens worden geteld als woordtekens en dat scenario's als dit niet zullen werken:

  • De "zijn" in "Wat _are_ je denkt?"
  • De "zijn" in "lol u dunno wut those are4?"

Als je iets nauwkeuriger wilt dan dit, zul je moeten beginnen met het parseren van Engelse syntaxis, en dat is een behoorlijk grote pot wormen (en veronderstelt in ieder geval dat je de syntaxis goed gebruikt, wat niet altijd een gegeven is).


113



Om te bepalen of een string een andere string bevat, kunt u de PHP-functie gebruiken strpos ().

int strpos ( string $haystack , mixed $needle [, int $offset = 0 ] )

<?php

$haystack = 'how are you';
$needle = 'are';

if (strpos($haystack,$needle) !== false) {
    echo "$haystack contains $needle";
}

?>

VOORZICHTIGHEID:

Als de naald waarnaar u zoekt zich aan het begin van de hooiberg bevindt, wordt positie 0 geretourneerd, als u dat doet == vergelijk dat zal niet werken, je zult een a moeten doen ===

EEN == teken is een vergelijking en test of de variabele / expressie / constante naar links dezelfde waarde heeft als de variabele / uitdrukking / constante aan de rechterkant.

EEN === teken is een vergelijking om te zien of twee variabelen / expressies / constanten gelijk zijn ANDhebben hetzelfde type, dat wil zeggen beide zijn tekenreeksen of beide zijn gehele getallen.


92



Gebruik makend van strstr() of stristr() als uw zoekopdracht moet worden uitgevoerd, is hoofdletterongevoelig een andere optie.


57



Kijk naar strpos():

<?php
    $mystring = 'abc';
    $findme   = 'a';
    $pos = strpos($mystring, $findme);

    // Note our use of ===. Simply, == would not work as expected
    // because the position of 'a' was the 0th (first) character.
    if ($pos === false) {
        echo "The string '$findme' was not found in the string '$mystring'.";
    }
    else {
        echo "The string '$findme' was found in the string '$mystring',";
        echo " and exists at position $pos.";
    }
?>

55



Als je het probleem "falsey" en "truthy" wilt vermijden, kun je substr_count gebruiken:

if (substr_count($a, 'are') > 0) {
    echo "at least one 'are' is present!";
}

Het is een beetje langzamer dan strpos, maar het vermijdt de vergelijkingsproblemen.


37



Gebruikmaken van case-insensitve matching gebruik makend van stripos():

if (stripos($string,$stringToSearch) !== false) {
    echo 'true';
}

37



Kijk eens naar SamGoody en Lego Stormtroopr reacties.

Als u op zoek bent naar een PHP-algoritme voor rangschik zoekresultaten op basis van nabijheid / relevantie van meerdere woorden hier komt een snelle en eenvoudige manier om zoekresultaten te genereren met alleen PHP:

Problemen met de andere booleaanse zoekmethoden zoals strpos(), preg_match(), strstr() of stristr() 

  1. kan niet naar meerdere woorden zoeken
  2. resultaten zijn ongeldig

PHP-methode gebaseerd op Vector ruimtemodel en tf-idf (term frequentie-inverse documentfrequentie):

Het klinkt moeilijk, maar is verrassend eenvoudig.

Als we naar meerdere woorden in een string willen zoeken, is het kernprobleem hoe we elk van hen een gewicht toekennen?

Als we de termen in een string zouden kunnen wegen op basis van hoe representatief ze zijn voor de string als geheel, we zouden onze resultaten kunnen bestellen door degenen die het best overeenkomen met de vraag.

Dit is het idee van het vectorruimtemodel, niet ver van hoe SQL full-text search werkt:

function get_corpus_index($corpus = array(), $separator=' ') {

    $dictionary = array();

    $doc_count = array();

    foreach($corpus as $doc_id => $doc) {

        $terms = explode($separator, $doc);

        $doc_count[$doc_id] = count($terms);

        // tf–idf, short for term frequency–inverse document frequency, 
        // according to wikipedia is a numerical statistic that is intended to reflect 
        // how important a word is to a document in a corpus

        foreach($terms as $term) {

            if(!isset($dictionary[$term])) {

                $dictionary[$term] = array('document_frequency' => 0, 'postings' => array());
            }
            if(!isset($dictionary[$term]['postings'][$doc_id])) {

                $dictionary[$term]['document_frequency']++;

                $dictionary[$term]['postings'][$doc_id] = array('term_frequency' => 0);
            }

            $dictionary[$term]['postings'][$doc_id]['term_frequency']++;
        }

        //from http://phpir.com/simple-search-the-vector-space-model/

    }

    return array('doc_count' => $doc_count, 'dictionary' => $dictionary);
}

function get_similar_documents($query='', $corpus=array(), $separator=' '){

    $similar_documents=array();

    if($query!=''&&!empty($corpus)){

        $words=explode($separator,$query);

        $corpus=get_corpus_index($corpus, $separator);

        $doc_count=count($corpus['doc_count']);

        foreach($words as $word) {

            if(isset($corpus['dictionary'][$word])){

                $entry = $corpus['dictionary'][$word];


                foreach($entry['postings'] as $doc_id => $posting) {

                    //get term frequency–inverse document frequency
                    $score=$posting['term_frequency'] * log($doc_count + 1 / $entry['document_frequency'] + 1, 2);

                    if(isset($similar_documents[$doc_id])){

                        $similar_documents[$doc_id]+=$score;

                    }
                    else{

                        $similar_documents[$doc_id]=$score;

                    }
                }
            }
        }

        // length normalise
        foreach($similar_documents as $doc_id => $score) {

            $similar_documents[$doc_id] = $score/$corpus['doc_count'][$doc_id];

        }

        // sort from  high to low

        arsort($similar_documents);

    }   

    return $similar_documents;
}

ZAAK 1

$query = 'are';

$corpus = array(
    1 => 'How are you?',
);

$match_results=get_similar_documents($query,$corpus);
echo '<pre>';
    print_r($match_results);
echo '</pre>';

RESULTAAT

Array
(
    [1] => 0.52832083357372
)

CASE 2

$query = 'are';

$corpus = array(
    1 => 'how are you today?',
    2 => 'how do you do',
    3 => 'here you are! how are you? Are we done yet?'
);

$match_results=get_similar_documents($query,$corpus);
echo '<pre>';
    print_r($match_results);
echo '</pre>';

RESULTATEN

Array
(
    [1] => 0.54248125036058
    [3] => 0.21699250014423
)

CASE 3

$query = 'we are done';

$corpus = array(
    1 => 'how are you today?',
    2 => 'how do you do',
    3 => 'here you are! how are you? Are we done yet?'
);

$match_results=get_similar_documents($query,$corpus);
echo '<pre>';
    print_r($match_results);
echo '</pre>';

RESULTATEN

Array
(
    [3] => 0.6813781191217
    [1] => 0.54248125036058
)

Er zijn genoeg verbeteringen aan te brengen maar het model biedt een manier om goede resultaten te halen uit natuurlijke zoekopdrachten, die geen Booleaanse operatoren hebben zoals strpos(), preg_match(), strstr() of stristr().

NOTA BENE

Optioneel elimineren van redundantie voorafgaand aan het doorzoeken van de woorden

  • waardoor de indexgrootte wordt verkleind en dit resulteert in minder opslagvereisten

  • minder schijf-I / O

  • snellere indexering en een dus snellere zoekactie.

1. Normalisatie

  • Converteer alle tekst naar kleine letters

2. Stopwoordeliminatie

  • Elimineer woorden uit de tekst die geen echte betekenis hebben (zoals 'en', 'of', 'de', 'voor', etc.)

3. Woordenboekvervanging

  • Vervang woorden door anderen die een identieke of vergelijkbare betekenis hebben. (ex: voorbeelden van 'honger' en 'honger' vervangen door 'honger')

  • Verdere algoritmische maatregelen (sneeuwbal) kunnen worden uitgevoerd om woorden verder te reduceren tot hun essentiële betekenis.

  • De vervanging van kleurnamen door hun hexadecimale equivalenten

  • De reductie van numerieke waarden door precisie te verminderen zijn andere manieren om de tekst te normaliseren.

MIDDELEN 


35



Een andere optie is om de strstr () functie. Zoiets als:

if (strlen(strstr($haystack,$needle))>0) {
// Needle Found
}

Let op: de functie strstr () is hoofdlettergevoelig. Gebruik de. Voor een niet-hoofdlettergevoelige zoekopdracht stristr () functie.


30