0
\$\begingroup\$

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.

asked Apr 20, 2015 at 14:03
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

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;
 }
 }
}
...
answered Apr 20, 2015 at 14:49
\$\endgroup\$
1
  • \$\begingroup\$ Welcome to CodeReview, hindmost. I hope you enjoy the site. \$\endgroup\$ Commented Apr 20, 2015 at 15:05

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.