PHP iki dizeleri arasındaki farkı vurgulamak

9 Cevap php

PHP iki dizeleri arasındaki farkı vurgulamak için en kolay yolu nedir?

Ben yeni metin yeşil ve kaldırılır metin içinde yığın taşması düzenleme tarih sayfasının çizgisinde düşünüyorum kırmızı olduğunu. Mevcut herhangi bir ön yazılı işlevleri veya sınıflar varsa, bu ideal olacaktır.

Şimdiden teşekkürler.

9 Cevap

Sen PHP Inline-Diff paketi kullanabilirsiniz. Bu sizin ihtiyaçlarınıza uygun, ve de oldukça özelleştirilebilir.

Ayrıca GPL lisanslı, yani tadını çıkarın oluyor!

Sadece başka bir dize içine bir dize dönüştürmek için düzenlemeler sayısını (kelimenin tam anlamıyla alınması değil) küçük hesaplamak için bir sınıf yazdı:

http://www.raymondhill.net/finediff/

Bu fark bir HTML versiyonunu işlemek için statik bir işlevi vardır.

Bu bir ilk versiyonu ve geliştirilmiş olması muhtemeldir, ama şu an itibariyle gayet güzel çalışıyor, bu yüzden Birisi ben gerektiği gibi, verimli kompakt diff üretmek için ihtiyaç halinde oraya atıyorum.

Edit: It's on Github now: https://github.com/gorhill/PHP-FineDiff

Eğer sağlam bir kitaplık istiyorsanız, Text_Diff (a PEAR paketi) oldukça iyi görünüyor. Bu oldukça serin bazı özelliklere sahiptir.

Xdiff için bir PECL eklentisi de var:

Özellikle:

PHP Manual Örnek:

<?php
$old_article = file_get_contents('./old_article.txt');
$new_article = $_POST['article'];

$diff = xdiff_string_diff($old_article, $new_article, 1);
if (is_string($diff)) {
    echo "Differences between two articles:\n";
    echo $diff;
}

Ben korkunç sorun vardı PEAR-temelli ve basit alternatifleri gösterilir hem de. Yani burada Unix diff komutunu (Açıkçası, bir Unix sistem üzerinde olması ya da çalışmak için bir çalışan Windows diff komutunu olması gerekir) güçlendirir bir çözümdür. En sevdiğiniz geçici dizini seçin ve isterseniz kodlarını döndürmek için istisnalar değiştirin.

/**
 * @brief Find the difference between two strings, lines assumed to be separated by "\n|
 * @param $new string The new string
 * @param $old string The old string
 * @return string Human-readable output as produced by the Unix diff command,
 * or "No changes" if the strings are the same.
 * @throws Exception
 */
public static function diff($new, $old) {
  $tempdir = '/var/somewhere/tmp'; // Your favourite temporary directory
  $oldfile = tempnam($tempdir,'OLD');
  $newfile = tempnam($tempdir,'NEW');
  if (!@file_put_contents($oldfile,$old)) {
    throw new Exception('diff failed to write temporary file: ' . 
         print_r(error_get_last(),true));
  }
  if (!@file_put_contents($newfile,$new)) {
    throw new Exception('diff failed to write temporary file: ' . 
         print_r(error_get_last(),true));
  }
  $answer = array();
  $cmd = "diff $newfile $oldfile";
  exec($cmd, $answer, $retcode);
  unlink($newfile);
  unlink($oldfile);
  if ($retcode != 1) {
    throw new Exception('diff failed with return code ' . $retcode);
  }
  if (empty($answer)) {
    return 'No changes';
  } else {
    return implode("\n", $answer);
  }
}

Ne arıyorsun bir "fark algoritması" dir. Hızlı bir google arama this solution götürdü. Ben test etmedim, ama belki size gereken ne yapacak.

Burada iki dizileri diff için kullanabileceğiniz kısa bir işlevdir. Bu LCS algoritması uygular:

function computeDiff($from, $to)
{
    $diffValues = array();
    $diffMask = array();

    $dm = array();
    $n1 = count($from);
    $n2 = count($to);

    for ($j = -1; $j < $n2; $j++) $dm[-1][$j] = 0;
    for ($i = -1; $i < $n1; $i++) $dm[$i][-1] = 0;
    for ($i = 0; $i < $n1; $i++)
    {
        for ($j = 0; $j < $n2; $j++)
        {
            if ($from[$i] == $to[$j])
            {
                $ad = $dm[$i - 1][$j - 1];
                $dm[$i][$j] = $ad + 1;
            }
            else
            {
                $a1 = $dm[$i - 1][$j];
                $a2 = $dm[$i][$j - 1];
                $dm[$i][$j] = max($a1, $a2);
            }
        }
    }

    $i = $n1 - 1;
    $j = $n2 - 1;
    while (($i > -1) || ($j > -1))
    {
        if ($j > -1)
        {
            if ($dm[$i][$j - 1] == $dm[$i][$j])
            {
                $diffValues[] = $to[$j];
                $diffMask[] = 1;
                $j--;  
                continue;              
            }
        }
        if ($i > -1)
        {
            if ($dm[$i - 1][$j] == $dm[$i][$j])
            {
                $diffValues[] = $from[$i];
                $diffMask[] = -1;
                $i--;
                continue;              
            }
        }
        {
            $diffValues[] = $from[$i];
            $diffMask[] = 0;
            $i--;
            $j--;
        }
    }    

    $diffValues = array_reverse($diffValues);
    $diffMask = array_reverse($diffMask);

    return array('values' => $diffValues, 'mask' => $diffMask);
}

Bu iki dizi oluşturur:

  • onlar fark göründükleri gibi unsurların bir listesi: dizi değerleri.
  • dizi maske: numaralarını içerir. 0: değişmeden, -1: kaldırıldı, 1: eklendi.

Bir karakter ile bir dizi doldurmak, bu inline farkı hesaplamak için kullanılabilir. Şimdi farklılıkları vurgulamak için sadece bir tek adım:

function diffline($line1, $line2)
{
    $diff = computeDiff(str_split($line1), str_split($line2));
    $diffval = $diff['values'];
    $diffmask = $diff['mask'];

    $n = count($diffval);
    $pmc = 0;
    $result = '';
    for ($i = 0; $i < $n; $i++)
    {
        $mc = $diffmask[$i];
        if ($mc != $pmc)
        {
            switch ($pmc)
            {
                case -1: $result .= '</del>'; break;
                case 1: $result .= '</ins>'; break;
            }
            switch ($mc)
            {
                case -1: $result .= '<del>'; break;
                case 1: $result .= '<ins>'; break;
            }
        }
        $result .= $diffval[$i];

        $pmc = $mc;
    }
    switch ($pmc)
    {
        case -1: $result .= '</del>'; break;
        case 1: $result .= '</ins>'; break;
    }

    return $result;
}

Örn.:

echo diffline('StackOverflow', 'ServerFault')

Çıktısı:

S<del>tackO</del><ins>er</ins>ver<del>f</del><ins>Fau</ins>l<del>ow</del><ins>t</ins> 

S-tackO erver f Faul {[(2)] t}

Ben PHP çekirdeğinin bu müthiş fonksiyonları bakarak tavsiye ederim:

similar_text - iki dizeleri arasındaki benzerliği hesaplar

http://www.php.net/manual/en/function.similar-text.php

levenshtein - İki dizge arasındaki hesaplama Levenshtein mesafe

http://www.php.net/manual/en/function.levenshtein.php

soundex - Bir dize soundex anahtarını hesaplayın

http://www.php.net/manual/en/function.soundex.php

metaphone - Bir dize metafon anahtarını hesaplayın

http://www.php.net/manual/en/function.metaphone.php