<?php
// decide if 1 or 2 is better
function selectBestImage($image1, $image2) {
// fix for strange array_filter behaviour
if ($image1 === 0)
return $image2;
list($path1, $info1) = $image1;
list($path2, $info2) = $image2;
$width1 = $info1[0];
$width2 = $info2[0];
// ugly if-block :(
if ($width1 == 260) {
return $image1;
} elseif ($width2 == 260) {
return $image2;
} elseif ($width1 == 265) {
return $image1;
} elseif ($width2 == 265) {
return $image2;
} elseif ($width1 == 600) {
return $image1;
} elseif ($width2 == 600) {
return $image2;
} elseif ($width1 == 220) {
return $image1;
} elseif ($width2 == 220) {
return $image2;
} else {
// nothing applied, so both are suboptimal
// just return one of them
return $image1;
}
}
function getBestImage($images) {
// step 1: is the absolutley best solution present?
foreach ($images as $key => $image) {
if (strpos($image, '-large') !== false) {
// yes! take it and ignore the rest.
return $image;
}
}
// step 2: no best solution
// prepare image widths so we don't have to get them more than once
foreach ($images as $key => $image) {
$images[$key] = array($image, getImageInfo($image));
}
// step 3: filter based on width
$bestImage = array_reduce($images, 'selectBestImage');
// the [0] index is because we have an array of 2-index arrays - ($path, $info)
return $bestImage[0];
}
$images = array('image1.png', 'image-large.png', 'image-foo.png', ...);
$bestImage = getBestImage($images);
?>
это должно работать (я не проверял это), но это неоптимально.
как это работает? во-первых, мы ищем абсолютно лучший результат, в данном случае -large
, потому что поиск подстрок недорог (в сравнении).
если мы не найдем -large
изображение, мы должны проанализировать ширину изображения (дороже! - поэтому мы предварительно рассчитаем их).
array_reduce вызывает функцию фильтрации, которая принимает 2 значения массива и заменяет эти два на одно возвращаемое функцией (лучшее). это повторяется до тех пор, пока в массиве не останется только одно значение.
это решение все еще неоптимально, потому что сравнения (даже если они дешевые) выполняются более одного раза. мои навыки обозначения big-O () немного (ха!) ржавые, но я думаю, что это O (n * logn). Решение Soulmerges лучше - O (n):)
Вы все еще можете улучшить решение Soulmerges, потому что второй цикл не нужен:
во-первых, упакуйте его в функцию, чтобы получить возврат в качестве замены-прерывания. если первый strstr совпадает, вернуть значение и игнорировать остальные. после этого вам не нужно хранить счет для каждого ключа массива. просто сравните ее с самой высокой переменной и, если новое значение выше, сохраните ее.
<?php
function getBestImage($images) {
$highestScore = 0;
$highestPath = '';
foreach ($images as $image) {
if (strpos($image, '-large') !== false) {
return $image;
} else {
list($width) = getImageInfo($image);
if ($width == 260 && $highestScore < 5) {
$highestScore = 5;
$highestPath = $image;
} elseif ($width == 265 && $highestScore < 4) {
$highestScore = 4;
$highestPath = $image;
} elseif ($width == 600 && $highestScore < 3) {
$highestScore = 3;
$highestPath = $image;
} elseif ($width == 220 && $highestScore < 2) {
$highestScore = 2;
$highestPath = $image;
} elseif ($highestScore < 1) {
// the loser case
$highestScore = 1;
$highestPath = $image;
}
}
}
return $highestPath;
}
$bestImage = getBestImage($images);
?>
не проверял, должен работать в O (n). не могу представить более быстрый и эффективный способ банкомата.