Jump to content
nephesh

Searching array for partial 'exact' match

Recommended Posts

I have a array of file path strings and trying to search the array for a string that would be the end of the path sting and return the index of the file path that contains the string. I've tried using something like this, but it finds the keyword in anyplace in the file path. I've also tried strripos() as well with the same results. Any suggestions?

function array_search_partial($arr, $keyword) {
    foreach ($arr as $index => $string) {
			if(strpos($string, $keyword) !== FALSE) {
				return $index;
			}
    }
}

 

Share this post


Link to post
Share on other sites

If you're dealing with file paths then you should probably be using file path functions. Like basename.

Share this post


Link to post
Share on other sites

That might have worked if I needed the whole filename. I need from the end to the first "-" (hyphen) to compare to the $keyword. (eg. lastname-firstname-username) Need to isolate username.

Share this post


Link to post
Share on other sites

I believe I've got it! Does this seem correct to you?

function array_search_partial($arr, $keyword) {
    foreach ($arr as $index => $string) {
			$userBase = basename($string);
			$test = substr_count($userBase, '-');
			if($test === 2) {
				if(preg_split("/[-]+/", $userBase)[2] == $keyword) {
					return $index;
				}
			}
    }
}

 

Share this post


Link to post
Share on other sites
Posted (edited)

According to your first post you have an array of paths/filenames EG

$arr = [
        'xxx/yyy/aaa-bbb-xxx.txt',
        'xxx/yyy/aaa-vcf.txt',
        'xxx/yyy/aaa-bbb-vbn.txt',
        'xxx/yyy/aaa-bbb-vvv.txt',
        'xxx/yyy/aaa-bbb-vcf.txt',
        'xxx/yyy/aaa-bbb-xcv.txt'
        ];

If that is the case, I think your preg_split line needs to add a "." so the file extension is excluded. I.E.

if(preg_split("/[-.]+/", $userBase)[2] == $keyword)
                  ^

then

echo array_search_partial($arr, 'vcf');                   //-->   4

Also, your function should return something (false ?) if no match is found.

Edited by Barand
  • Like 1

Share this post


Link to post
Share on other sites

Something like this could get your started

<?php
$filepaths = array();
$filepaths[] = "/path/to/file/bob-villa-bvilla35";
$filepaths[] = "/path/to/file/jim-bob-dinosaur64";
$filepaths[] = "/path/to/file/abe-lincoln-alinkler";
$filepaths[] = "/path/to/file/michael-jordan-ncairman";
$filepaths[] = "/path/to/file/bart-simpson-eatmyshorts";

$s = "air";
$regex = "#\/path\/to\/file\/([^$]+)#";
$userregex = "#^\w+-\w+-(.*".$s.".*)$#";

$userKey = array_filter($filepaths, function($e) use ($s,$regex,$userregex){
        $userString = preg_match($regex, $e, $m);
        $user = preg_match($userregex, $m[1], $o);
        if(count($o)) return strpos($o[1],$s)+1; 
});

$key = key($userKey);
echo "The key is: " . $key . "<br>" . $filepaths[$key];

?>

That would give you

Quote

The key is: 3
/path/to/file/michael-jordan-ncairman

 

Share this post


Link to post
Share on other sites

One question though, why would I need to return "false" if nothing is found? It will always find something. And when I've tried adding it as below it doesn't return the correct results. (Also, to make this clear the file paths in the array don't contain the extension.)

function array_search_partial($arr, $keyword) {
    foreach ($arr as $index => $string) {
			$userBase = basename($string);
			$test = substr_count($userBase, '-');
			if($test === 2) {
				if(preg_split("/[-]+/", $userBase)[2] == $keyword) {
					return $index;
				} else {
				return false;
			}
		}	
}

 

Share this post


Link to post
Share on other sites

Do you test your code? Aside from the logic being wrong it is also missing a "}"

In the code below using your function, a search for "dinosaur64"" should return "1"

$filepaths = array();
$filepaths[] = "/path/to/file/bob-villa-bvilla35";
$filepaths[] = "/path/to/file/jim-bob-dinosaur64";
$filepaths[] = "/path/to/file/abe-lincoln-alinkler";
$filepaths[] = "/path/to/file/michael-jordan-ncairman";
$filepaths[] = "/path/to/file/bart-simpson-eatmyshorts";

function array_search_partial($arr, $keyword) {
    foreach ($arr as $index => $string) {
            $userBase = basename($string);
            $test = substr_count($userBase, '-');
            if($test === 2) {
                if(preg_split("/[-]+/", $userBase)[2] == $keyword) {
                    return $index;
                } else {
                    return false;
                }
            }
    }    
}

$index = array_search_partial($filepaths, 'dinosaur64');
var_dump($index);                                               //-->   bool(false)           (Should be "1")

 

27 minutes ago, nephesh said:

It will always find something.

You can guarantee that no-one will search for a keyword that isn't there?

(At the moment it will only ever find the first item.)

Edited by Barand

Share this post


Link to post
Share on other sites

Yes, I tested my code. I am sorry, I had just added in the else statement for this post, as I have it working correctly as this:

function array_search_partial($arr, $keyword) {
    foreach ($arr as $index => $string) {
			$userBase = basename($string);
			$test = substr_count($userBase, '-');
			if($test === 2) {
				if(preg_split("/[-]+/", $userBase)[2] == $keyword) {
					return $index;
				} 
			}
		}	
}

It only needs to find one item, as the $keyword is a unique identifier. But you are right I should return false to the caller. Which is :

$index = array_search_partial($profilePaths, $userName);
      if($index){ 
          $profileLink = "/".$profilePaths[$index].".html";
      } 

 

Share this post


Link to post
Share on other sites

I changed to function below so it returns "false" if the keyword is not found. 

If the matched item is the first in the array its index will be "0" so your test for 

if ($index)

will fail as 0 evaluates to false. You need to explicitly test for a Boolean false as below

function array_search_partial($arr, $keyword) {
    foreach ($arr as $index => $string) {
            $userBase = basename($string);
            $test = substr_count($userBase, '-');
            if($test === 2) {
                if(preg_split("/[-]+/", $userBase)[2] == $keyword) {
                    return $index;
                } 
            }
    }
    // if we get here it hasn't found the keyword
    return false;    
}

$index = array_search_partial($profilePaths, $userName);
if($index !== false){                                           // check it isn't (boolean) false
    $profileLink = "/".$profilePaths[$index].".html";
} 

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.