2

I'm trying to automate sifting through my online bank statements. Here's a trivial example of what I need.

I have an array of restaurants against which I sort my credit card statements:

$restaurants = array(
    array("vendor" => "default",
            "type" => "default"
    ),
    array("vendor" => "dunkin",
            "type" => "pastry"
    ),
    array("vendor" => "mcdonald",
            "type" => "fastfood"
    ),
    array("vendor" => "olive",
            "type" => "italian"
    )
);

The statement entries themselves can be a rather descriptive string:

$string = "McDonald's Restaurants Incorporated";

I've tried using array_search and in_array, but they seem to do the reverse of what I need, or they need an exact match like in the example below, but it is not what I need:

$result = array_search($string, array_column($restaurants, 'vendor'));
return $restaurants[$result]['type'];

// returns "default" because "McDonald's Restaurants Incorporated" != "mcdonald"

I would like to be able to match the array value "mcdonald" to any string that contains that chunk of it, and then return type "fastfood" for it. Don't worry about handling multiple occurrences.

4 Answers 4

3

You'll need a combination of things - a search-in-string method, and for it to be case insensitive.

You can accomplish this with something like this:

/**
 * Perform a string-in-string match case insensitively
 * @param  string $string
 * @param  array  $restaurants
 * @return string|false
 */
function findRoughly($string, $restaurants)
{
    $out = false;
    foreach ($restaurants as $restaurant) {
        // Set up the default value
        if ($restaurant['type'] == 'default' && !$out) {
            $out = $restaurant['type'];
            // Stop this repetition only
            continue;
        }
        // Look for a match
        if (stripos($string, $restaurant['vendor']) !== false) {
            $out = $restaurant['type'];
            // Match found, stop looking
            break;
        }
    }
    return $out;
}

And use it like so:

$result = findRoughly("McDonald's", $restaurants);

Example here.

Sign up to request clarification or add additional context in comments.

3 Comments

Works exactly right! Thank you for the example code, much appreciated.
This could be done more efficiently. Why do you use the temporary variable $out? Why not return $restaurant['type'] as soon as it is found and have a default return statement outside of the loop? This would shorten your function to 9 lines not counting comments.
Hi @blasko, the temporary variable is to handle a situation where the default value might not be at the start of the array but perhaps the middle or end. If neither a match not default is found, return false
2

I don't think there's a function in PHP that will handle this quite as cleanly as you want. But you can whip up a quick function to loop through the array looking for matches:

$type = call_user_func( function( $restaurants, $string ) {
    foreach ( $restaurants as $restaurant ) {
        if ( stripos( $string, $restaurant['vendor'] ) !== FALSE ) {
            return $restaurant['type'];
        }
    }

    return $restaurant[0]['type'];
}, $restaurants, $string );

If $string is "McDonald's Restaurants Incorporated", then $type will be "fastfood". The above makes the assumption that the first instance in the array is your default return if none of the specified values match.

I just built this as an anonymous function/closure out of convenience, which I usually would to do cleanly enclose something I only plan to run once. But it may be cleaner as a named function in your application.

Comments

0

I took a different (functional) approach by using array_map and array_filter. It's rather compact due to the use of builtin functions, and gets the job done.

 // Anonymous function which gets passed to array_map as a callback
 // Checks whether or not the vendor is in the $key_string (your restaurant)
$cmp = function ($array) use ($key_string) {
    if (stristr($key_string, $array['vendor'])) {
        return $array['type'];
    }
    return "default";
};

function validResult($item) {
    return isset($item) && gettype($item)=="string";
}

$key_string = "McDonald's Restaurants Incorporated";
$results = array_map($cmp, $restaurants);
$results = array_pop(array_filter($results, validResult));

Comments

-1

I got fixated on the in_array portion of the question. Editing this to use strpos instead.

Try this:

foreach($restaurants as $restaurant)
{
     if(strpos($restaurant['vendor'], $string) !== FALSE)
     {
          return $restaurant['type']; //Or add to an array/do whatever you want with this value.
     }
}

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

1 Comment

The second parameter of in_array() cannot be a string.

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.