1

So basically, I am simply trying to search for a string within a string.

Although, it is a little trickier than that.

I have three small strings, one, two, three

And I have one large string, which is saved as a variable and is quite long.. A few paragraphs long actually.

I need to create a function that allows me to see which string occurs first.

For example, a string like this:

Hello, testing testing one test some more two

Will return one since it occurred before two.

Another example:

Test a paragraph three and testing some more one test test two

Will return three since it occurred before both one and two.

Does anyone have any suggestions or examples on how to do this? Very new to PHP and not to sure how to go about doing this. Thanks!

2
  • 1
    Use stripos on every "small string" and see which position is the minimum? Commented Sep 11, 2013 at 2:56
  • Do you want the position or just which string comes first? Commented Sep 11, 2013 at 3:08

6 Answers 6

5

Use preg_match() with a simple alternation:

if (preg_match('/one|two|three/', $string, $matches)) {
    echo $matches[0];
}

Results:

Hello, testing testing one test some more two
-> one

Test a paragraph three and testing some more one test test two
-> three

If you need the position as well, you can add a flag:

if (preg_match('/one|two|three/', $string, $matches, PREG_OFFSET_CAPTURE)) {
    echo 'Found ' . $matches[0][0] . ' @ ' . $matches[0][1];
}

As a function:

function findFirst($string, array $needles)
{
    $pattern = '/' . join('|', array_map(function($str) {
        return preg_quote($str, '/');
    }, $needles)) . '/';

    if (preg_match($pattern, $string, $matches)) {
        return $matches[0];
    } else {
        return false;
    }
}

To use:

echo findFirst($string, array('one', 'two', 'three'));
Sign up to request clarification or add additional context in comments.

2 Comments

Great answer, although I find having a function easier to read and modify. Will definitely use this next time round since it is far more simplistic. Thanks!
@fizzix I've updated my answer to include what a function would look like.
1

Try something like this:

$string = 'Hello, testing testing one test some more two';
$words = Array("one", "two", "three");
$low_pos = strlen($string);
$first = '';
foreach($words as $word)
{
    $pos = strpos($string, $word);
    echo "Found ".$word." at ".$pos."<br />";
    if($pos !== false && $pos < $low_pos)
    {
        $low_pos = $pos;
        $first = $word;
    }
}

echo $string."<br />";
echo "FIRST: ".$first;

Output:

Found one at 23
Found two at 42
Found three at 
Hello, testing testing one test some more two
FIRST: one

Comments

1

See http://www.php.net/manual/en/function.strpos.php

Simply something like

$longString = "Hello, testing testing one test some more two";
$onePosition = strpos($longString, "one");
$twoPosition = strpos($longString, "two");
$threePosition = strpos($longString, "three");

$onePosition; // 23
$twoPosition; // 42
$threePosition; // -1

Then you would just compare each variable to find the lowest. Clunky but for 3 variables not much work.

3 Comments

But wouldn't $threePosition be the lowest since it is -1?
You would check for > 0.
strpos() returns false if the needle is not found (not -1). You'd have to first check that each variable is not false, and then compare the ones that aren't against each other.
1

This should work:

<?php

    $arrWords = array("one", "two", "three");
    $strInput = "Test a paragraph three and testing some more one test test two";

    function getFirstOccurrence($strInput, $arrWords) {
        $arrInput = explode(" ", $strInput);
        foreach($arrInput as $strInput) {
            if(in_array($strInput, $arrWords)) {
                return $strInput;
            }
        }
        return null;
    }

    print "First word is: " . getFirstOccurrence($strInput, $arrWords);

?>

1 Comment

Think your answer is probably the most reliable, especially with the implementation of the array search. Thanks for your help!
1

Here's a sample algorithm:

function getFirstWord(array $needles, $haystack) {
    $best = null; //the best position
    $first = null; //the first word

    foreach($needles as $needle) {
        $pos = strpos($haystack, $needle);
        if($pos !== false) {
            if($best === null || $pos < $best) {
                $best = $pos;
                $first = $needle;
            }
        }
    }

    //returns the first word, or null if none of $needles found
    return $first;
}

$needles = array('one', 'two', 'three');
echo getFirstWord($needles, 'Hello, testing testing one test some more two'); // one
echo getFirstWord($needles, 'Test a paragraph three and testing some more one test test two'); // three

An optimal solution would minimise iterations over $haystack. You could start at the beginning of the string, and each time you advance a character, look for any of the $needles starting at the current position. As soon as you find one, bingo.

Comments

0

If you want to get fancy you can use a closure with array_map, array_filter, array_search and min.

function whichFirst(array $list, $string){
    // get a list of the positions of each word
    $positions = array_map(function($val) use ($string){
                                return strpos($string, $val);
                            }, $list);
    // remove all of the unfound words (where strpos returns false)
    $positions = array_filter($positions, function ($x){ return $x !== false; });

    // get the value with the key matching the lowest position.
    $key = array_search(min($positions), $positions);

    return $list[$key];
}

Example:

$str = "Hello, testing testing one test some more two";
$list = ["one","two","three"];

echo whichFirst($list, $str);
// outputs one

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.