5 kurallara dayalı bir PHP dizi veri çekerek yardım

4 Cevap php

Ben görüntü filepaths dizileri ile çalışıyorum. Tipik bir dizi içinde saklanan 5 görüntü filepaths olabilir.

Her dizi için, ben koleksiyonu için bir simgesi olarak görüntülemek için sadece "iyi" fotoğraf çekin istiyorum.

Ben çok kafa karıştırıcı döngü ve dizileri bulmak ve bu yapısı nasıl anlamaya çalışıyorum 4 saat sonra, ben bir kayıp değilim.

İşte ben çalışıyorum kurallar şunlardır:

  1. Çok iyi fotoğrafları kendi filepaths içinde "-büyük" var. Tüm diziler onlar böyle görüntüleri var, ama eğer onlar yapmak, o zaman ben dışarı koparmak istiyorum fotoğraf bulunuyor.

  2. Sonraki en iyi resimler 260px genişliğinde. Ben getimagesize ile bu kadar bakabilirsiniz. Bunlardan birini bulursanız, ben seyir durdurmak ve onu kullanmak istiyorum.

  3. Sonraki en iyi fotoğrafları 265 genişliğindedir. Ben bir tane bulursam ben bunu kullanmak ve arayan durdurmak istiyorum.

  4. Sonraki en iyi resimler 600px genişliğinde. Aynı şey.

  5. Daha sonra 220px geniş.

Döngüler için 5 ayrı gerekir mi? 5 için-döngüler iç içe

İşte ben çalışıyorum ne:

if $image_array{    
  loop through $image_array looking for "-large"
  if you find it, print it and break;             

  if you didn't find it, loop through $image_array looking for 260px wide.
  if you find it, print it and break;
}

ve böylece ....

Ama bu çalışıyor görünmüyor.

Ben bu kriterlere göre en iyi tek bir görüntü için benim dizisi "arama" istiyorum. Bu birinci tip bulamazsanız, o zaman böylece ikinci arar. Bu nasıl yapılır?

4 Cevap

(Önemsiz az jenerik, yavaş) başka bir yaklaşımdır. Sadece kurallar tek tek kontrol edin:

function getBestFile($files) {
    foreach ($files as $arrayKey => $file) {
        if (strstr($file, '-large') !== FALSE) {
            return $file;
        }
    }
    foreach ($files as $arrayKey => $file) {
        if (is260wide($file)) {
            return $file;
        }
    }
    // ...
}

Sen 3 döngüler ve varsayılan bir seçim gerekir.

loop through $image_array looking for "-large"
if you find it, return it;

if you didn't find it, loop through $image_array
get image width
if prefered width (260px), return it.
if $sizes[$width] not set, add filename

loop a list of prefered sizes in order and see if it is set in $sizes
if you find it, return it;

return the first image or default image;
<?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);

?>

Bu (i test etmedi) çalışması gerekir, ama suboptimaldir.

nasıl çalışır? Bir alt dizelerin arıyor (comparsion) ucuz olması nedeniyle ilk, biz, bu durumda, -large, kesinlikle iyi sonuç için bakmak.

(! - yani biz bunları önceden hesaplamak daha pahalı) bir -large görüntü bulmak yoksa biz görüntü genişlikleri analiz etmek gerekir.

array_reduce 2 dizi değerlerini alır ve işlevi tarafından bir dönüş (iyi bir) tarafından bu iki yerine bir filtreleme işlevini çağırır. dizideki geriye tek bir değer yoktur kadar bu tekrarlanır.

karşılaştırmalar (onlar ucuz bile) bir kez daha yapılır çünkü bu çözüm, hala suboptimaldir. benim büyük-O () notasyonu becerileri biraz (ha!) Paslı, ama ben O (n * logn) olduğunu düşünüyorum. soulmerges çözüm daha iyi bir - O (n) :)

İkinci döngü gerekli değildir, çünkü hala, soulmerges çözüm getirebileceği:

Eğer bir mola yerine dönüş var yani ilk, bir fonksiyonun içine paketi. İlk strstr eşleşirse, değerini döndürür ve geri kalanı görmezden. sonra, her dizi anahtar için puan saklamak zorunda değilsiniz. Sadece highestKey değişkene karşılaştırmak ve yeni değeri yüksek ise, saklayın.

<?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);

?>

, test etmedi O (n) çalışması gerekir. daha hızlı, daha verimli bir şekilde atm hayal edemiyorum.

Ben birçok kurallar geçerli nasıl bağlı dosyalara puan atamak olacaktır. Başkalarına supercede için belli kurallar istiyorsanız, bu kural için daha fazla puan verebilir.

define('RULE_POINTS_LARGE', 10);
define('RULE_POINTS_260_WIDE', 5);
// ...

$points = array();
foreach ($files as $arrayKey => $file) {
    $points[$arrayKey] = 0;
    if (strstr($filename, '-large') !== FALSE) {
        $points[$arrayKey] += RULE_POINTS_LARGE;
    }
    // if ...
}

// find the highest value in the array:
$highestKey = 0;
$highestPoints = 0;
foreach ($points as $arrayKey => $points) {
    if ($files[$arrayKey] > $highestPoints) {
        $highestPoints = $files[$arrayKey];
        $highestKey = $arrayKey;
    }
}

// The best picture is $files[$highestKey]

Bir daha yan not: Bir değer senin kurallarını Givign katları bir kural tüm diğerlerinden daha 'güçlü' olabilir sağlayacaktır. Örnek: 5 kuralları -> kural değerleri (1, 2, 4, 8, 16).

  • 1 < 2
  • 1 + 2 < 4
  • 1 + 2 + 4 ' 8
  • vb