Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I'm using a levenshtein matching algorithm to match a title to a filename (for anime). I either use the main show title for matching or its alternative titles (flexget_titles).

For that I have the following snippet of code.

public function matchFilenameToShow($filename)
{
    $shows = $this->shows->getAll();
    $shortest = -1;
    $clean_name = $this->removeEpisodeNumber($this->cleanFilename($filename));
    foreach ($shows as $show) {
        if (!empty($show->flexget_titles_array)) {
            foreach ($show->flexget_titles_array as $title) {
                // calculate the distance between the input string filename,
                // and the current show name
                $lev = levenshtein(strtolower($clean_name), strtolower($title));
                // if this distance is less than the next found shortest
                // distance, OR if a next shortest distance to the word has not yet been found
                if ($lev <= $shortest || $shortest < 0) {
                    // set the closest match, and shortest distance
                    $matchedShow = $show;
                    $shortest = $lev;
                }
            }
        } else {
            // calculate the distance between the input string filename,
            // and the current show name
            $lev = levenshtein(strtolower($clean_name), strtolower($show->title));
            // if this distance is less than the next found shortest
            // distance, OR if a next shortest distance to the word has not yet been found
            if ($lev <= $shortest || $shortest < 0) {
                // set the closest match, and shortest distance
                $matchedShow = $show;
                $shortest = $lev;
            }
        }
    }
    return $matchedShow;
}

Obviously there is code repetition and I want to refactor this. However I'm not sure how to do it. I have a feeling that I need to extract that levenshtein part to a separate method, but I need to return 2 variables.

share|improve this question

1 Answer 1

up vote 2 down vote accepted

You can create "fallback" version of nested array in the case when $show->flexget_titles_array is empty and handle it with the same nested foreach loop:

...
foreach ($shows as $show) {
    ($arr = $show->flexget_titles_array) || ($arr = array($show->title));
    foreach ($arr as $title) {
        // calculate the distance between the input string filename,
        // and the current show name
        $lev = levenshtein(strtolower($clean_name), strtolower($title));
        // if this distance is less than the next found shortest
        // distance, OR if a next shortest distance to the word has not yet been found
        if ($lev <= $shortest || $shortest < 0) {
            // set the closest match, and shortest distance
            $matchedShow = $show;
            $shortest = $lev;
        }
    }
}
...
share|improve this answer
    
Welcome to CodeReview, hindmost. I hope you enjoy the site. –  Legato Apr 20 at 15:05

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.