7

I have an array like below:

$fruits = array("apple","orange","papaya","grape")

I have a variable like below:

$content = "apple";

I need to filter some condition like: if this variable matches at least one of the array elements, do something. The variable, $content, is a bunch of random characters that is actually one of these available in the array data like below:

$content = "eaplp"; // it's a dynamically random char from the actual word "apple`

what have I done was like the below:

$countcontent = count($content);

for($a=0;$a==count($fruits);$a++){

      $countarr = count($fruits[$a]);

      if($content == $fruits[$a] && $countcontent == $countarr){
          echo "we got".$fruits[$a];
      }

}

I tried to count how many letters these phrases had and do like if...else... when the total word in string matches with the total word on one of array data, but is there something that we could do other than that?

Gagantous
  • 432
  • 6
  • 29
  • 69
  • How do you want to handle the situation when more than one word can be mapped to the random letters array? – sevavietl May 08 '18 at 07:39
  • for my situation, i just need to search only one word from the whole word inside an array, because there is only one the word that matches with the random word @sevavietl, there is no multiple word that similar like `apple custard` , `apple pie` . Only `apple`. – Gagantous May 08 '18 at 08:06
  • `in_array()` ... – Pedro Lobito May 09 '18 at 03:19

9 Answers9

16

We can check if an array contains some value with in_array. So you can check if your $fruits array contains the string "apple" with,

in_array("apple", $fruits)

which returns a boolean.

If the order of the letters is random, we can sort the string alphabetically with this function:

function sorted($s) {
    $a = str_split($s);
    sort($a);
    return implode($a);
}  

Then map this function to your array and check if it contains the sorted string.

$fruits = array("apple","orange","papaya","grape");
$content = "eaplp";
$inarr = in_array(sorted($content), array_map("sorted", $fruits));

var_dump($inarr);
//bool(true)

Another option is array_search. The benefit from using array_search is that it returns the position of the item (if it's found in the array, else false).

$pos = array_search(sorted($content), array_map("sorted", $fruits));

echo ($pos !== false) ? "$fruits[$pos] found." : "not found.";  
//apple found.
t.m.adam
  • 15,106
  • 3
  • 32
  • 52
  • How do i echo the result like "apple found" or " papaya found" ? I know tgat the result will be "true" but how do i echo the real words? I mean not the random character that were given – Gagantous May 04 '18 at 05:48
  • 1
    You'll have to loop over the array or use `array_search`. I'll update my answer. – t.m.adam May 04 '18 at 05:59
5

This will also work but in a slightly different manner.

I split the strings to arrays and sort them to match eachoter.
Then I use array_slice to only match the number of characters in $content, if they match it's a match.
This means this will match in a "loose" way to with "apple juice" or "apple curd".

Not sure this is wanted but figured it could be useful for someone.

$fruits = array("apple","orange","papaya","grape","apple juice", "applecurd");
$content = "eaplp";
$content = str_split($content);
$count = count($content);

Foreach($fruits as $fruit){
    $arr_fruit = str_split($fruit);
    // sort $content to match order of $arr_fruit
    $SortCont = array_merge(array_intersect($arr_fruit, $content), array_diff($content, $arr_fruit));
    // if the first n characters match call it a match
    If(array_slice($SortCont, 0, $count) == array_slice($arr_fruit, 0, $count)){
        Echo "match: " . $fruit ."\n";
    }
}

output:

match: apple
match: apple juice
match: applecurd

https://3v4l.org/hHvp3
It is also comparable in speed with t.m.adams answer. Sometimes faster sometimes slower, but note how this code can find multiple answers. https://3v4l.org/IbuuD

Andreas
  • 23,610
  • 6
  • 30
  • 62
4

Here's a clean approach. Returns unscrambled value early if found, otherwise returns null. Only returns an exact match.

function sortStringAlphabetically($stringToSort)
{
    $splitString = str_split($stringToSort);
    sort($splitString);

    return implode($splitString);
}

function getValueFromRandomised(array $dataToSearch = [], $dataToFind)
{
    $sortedDataToFind = sortStringAlphabetically($dataToFind);

    foreach ($dataToSearch as $value) {
        if (sortStringAlphabetically($value) === $sortedDataToFind) {
            return $value;
        }
    }

    return null;
}

$fruits = ['apple','orange','papaya','grape'];
$content = 'eaplp';

$dataExists = getValueFromRandomised($fruits, $content);

var_dump($dataExists);
// string(5) "apple" 

Not found example:

$content = 'eaplpo';
var_dump($dataExists);
// NULL

Then you can use it (eg) like this:

echo !empty($dataExists) ? $dataExists . ' was found' : 'No match found';

NOTE: This is case sensitive, meaning it wont find "Apple" from "eaplp". That can be resolved by doing strtolower() on the loop's condition vars.

James
  • 4,644
  • 5
  • 37
  • 48
4

I think this is the simplest way to answer that question. some of the algorithm above seems to be "overkill".

$fruits = array("apple","orange","papaya","grape");
$content = "eaplp";

    foreach ($fruits as $key => $fruit) {
        $fruit_array = str_split($fruit); // split the string into array
        $content_array = str_split($content); // split the content into array

        // check if there's no difference between the 2 new array
        if ( sizeof(array_diff($content_array, $fruit_array)) === 0 ) {
            echo "we found the fruit at key: " . $key;
            return;
        }
    }
4

What about using only native PHP functions.

$index = array_search(count_chars($content), array_map('count_chars', $fruits));

If $index is not null you will get the position of $content inside $fruits.

P.S. Be aware that count_chars might not be the fastest approach to that problem.

cb0
  • 8,415
  • 9
  • 52
  • 80
4

With a random token to search for a value in your array, you have a problem with false positives. That can give misleading results depending on the use case.

On search cases, for example wrong typed words, I would implement a filter solution which produces a matching array. One could sort the results by calculating the levenshtein distance to fetch the most likely result, if necessary.

String length solution

Very easy to implement.

False positives: Nearly every string with the same length like apple and grape would match.

Example:

$matching = array_filter($fruits, function ($fruit) use ($content) {
    return strlen($content) == strlen($fruit);
});
if (count($matching)) {
    // do your stuff...
}

Regular expression solution

It compares string length and in a limited way containing characters. It is moderate to implement and has a good performance on big data cases.

False positives: A content like abc would match bac but also bbb.

Example:

$matching = preg_grep(
     '#['.preg_quote($content).']{'.strlen($content).'}#',
      $fruits
);
if (count($matching)) {
    // do your stuff...
}

Alphanumeric sorting solution

Most accurate but also a slow approach concerning performance using PHP.

False positives: A content like abc would match on bac or cab.

Example:

$normalizer = function ($value) {
    $tokens = str_split($value);
    sort($tokens);
    return implode($tokens);
};
$matching = array_filter($fruits, function ($fruit) use ($content, $normalizer) {
    return ($normalizer($fruit) == $normalizer($content));
});
if (count($matching)) {
    // do your stuff...
}
Trendfischer
  • 7,112
  • 5
  • 40
  • 51
3

How about looping through the array, and using a flag to see if it matches?

$flag = false;

foreach($fruits as $fruit){
    if($fruit == $content){
        $flag = true;
    }
}

if($flag == true){
    //do something
}
Jack Perry
  • 321
  • 1
  • 4
  • 13
3

I like t.m.adams answer but I also have a solution for this issue:

array_search_random(string $needle, array $haystack [, bool $strictcase = FALSE ]);

Description: Searches a string in array elements regardless of the position of the characters in the element.

  • needle: the caracters you are looking for as a string
  • haystack: the array you want to search
  • strictcase: if set to TRUE needle 'mood' will match 'mood' and 'doom' but not 'Mood' and 'Doom', if set to FALSE (=default) it will match all of these.

Function:

 function array_search_random($needle, $haystack, $strictcase=false){

  if($strictcase === false){
   $needle = strtolower($needle);     
  }

  $needle = str_split($needle);
            sort($needle);
  $needle = implode($needle);

  foreach($haystack as $straw){

   if($strictcase === false){
    $straw = strtolower($straw);     
   }

   $straw = str_split($straw);
            sort($straw);
   $straw = implode($straw);

   if($straw == $needle){
    return true;
   }

  }

  return false;

 }
Bernhard
  • 1,852
  • 11
  • 19
-2

if(in_array("apple", $fruits)){ true statement }else{ else statement }