วิธีที่ง่ายที่สุดในการเน้นความแตกต่างระหว่างสองสตริงใน PHP คืออะไร?
ฉันกำลังคิดตามบรรทัดของหน้าประวัติการแก้ไขสแต็คโอเวอร์โฟลว์ที่ข้อความใหม่เป็นสีเขียวและข้อความที่ลบออกเป็นสีแดง หากมีฟังก์ชั่นหรือคลาสใด ๆ ที่เขียนไว้ล่วงหน้าจะเหมาะที่สุด
วิธีที่ง่ายที่สุดในการเน้นความแตกต่างระหว่างสองสตริงใน PHP คืออะไร?
ฉันกำลังคิดตามบรรทัดของหน้าประวัติการแก้ไขสแต็คโอเวอร์โฟลว์ที่ข้อความใหม่เป็นสีเขียวและข้อความที่ลบออกเป็นสีแดง หากมีฟังก์ชั่นหรือคลาสใด ๆ ที่เขียนไว้ล่วงหน้าจะเหมาะที่สุด
คำตอบ:
คุณสามารถใช้แพ็คเกจ PHP Horde_Text_Diff
อย่างไรก็ตามแพ็คเกจนี้ไม่สามารถใช้งานได้อีกต่อไป
เพิ่งเขียนคลาสเพื่อคำนวณจำนวนการแก้ไขที่น้อยที่สุด (เพื่อไม่ให้เป็นจริง) เพื่อแปลงสตริงหนึ่งเป็นสตริงอื่น:
http://www.raymondhill.net/finediff/
มันมีฟังก์ชั่นแบบคงที่ในการเรนเดอร์ HTML รุ่นต่าง ๆ
มันเป็นรุ่นแรกและมีแนวโน้มที่จะได้รับการปรับปรุง แต่มันใช้งานได้ดี ณ ตอนนี้ดังนั้นฉันจึงขว้างมันออกมาในกรณีที่มีคนต้องการสร้างความแตกต่างที่มีขนาดกะทัดรัดได้อย่างที่ต้องการ
แก้ไข: อยู่ใน Github ทันที: https://github.com/gorhill/PHP-FineDiff
ถ้าคุณต้องการห้องสมุดที่มีประสิทธิภาพText_Diff (แพ็คเกจแพร์) ดูเหมือนจะค่อนข้างดี มันมีคุณสมบัติเจ๋ง ๆ
นี่เป็นสิ่งที่ดีเช่นกัน http://paulbutler.org/archives/a-simple-diff-algorithm-in-php/
การแก้ปัญหานั้นไม่ง่ายอย่างที่คิดและปัญหาก็รบกวนฉันมาประมาณหนึ่งปีก่อนที่ฉันจะรู้ได้ ฉันจัดการเพื่อเขียนอัลกอริทึมของฉันใน PHP ในรหัส 18 บรรทัด มันไม่ใช่วิธีที่มีประสิทธิภาพที่สุดในการทำ diff แต่มันอาจเป็นวิธีที่เข้าใจง่ายที่สุด
มันทำงานโดยการค้นหาลำดับของคำที่ยาวที่สุดที่ใช้ร่วมกันกับทั้งสองสตริงและวนซ้ำในลำดับที่ยาวที่สุดของส่วนที่เหลือของสตริงจนกระทั่งสตริงย่อยไม่มีคำที่เหมือนกัน ณ จุดนี้จะเพิ่มคำศัพท์ใหม่ที่เหลือเป็นการแทรกและคำเก่าที่เหลือเป็นการลบ
คุณสามารถดาวน์โหลดซอร์สได้ที่นี่: PHP SimpleDiff ...
if($matrix[$oindex][$nindex] > $maxlen){
Undefined variable: maxlen
นี่คือฟังก์ชั่นสั้น ๆ ที่คุณสามารถใช้เพื่อกระจายสองอาร์เรย์ มันใช้อัลกอริทึมLCS :
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);
}
มันสร้างสองอาร์เรย์:
หากคุณเติมอาเรย์ด้วยอักขระมันสามารถใช้ในการคำนวณความแตกต่างแบบอินไลน์ ตอนนี้เป็นเพียงขั้นตอนเดียวเพื่อเน้นความแตกต่าง:
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;
}
เช่น.:
echo diffline('StackOverflow', 'ServerFault')
จะส่งออก:
S<del>tackO</del><ins>er</ins>ver<del>f</del><ins>Fau</ins>l<del>ow</del><ins>t</ins>
StackOerverฉฟอลโอ๊ยเสื้อ
หมายเหตุเพิ่มเติม:
computeDiff is not found
นอกจากนี้ยังมีส่วนขยาย PECL สำหรับ xdiff:
โดยเฉพาะอย่างยิ่ง:
ตัวอย่างจากคู่มือ PHP:
<?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;
}
ฉันมีปัญหาอย่างมากกับทั้งลูกแพร์และทางเลือกที่ง่ายกว่าที่แสดง ดังนั้นนี่คือโซลูชันที่ใช้ประโยชน์จากคำสั่ง Unix diff (แน่นอนว่าคุณต้องอยู่ในระบบ Unix หรือมีคำสั่ง Windows diff ที่ใช้งานได้เพื่อให้ทำงานได้) เลือกไดเรกทอรีชั่วคราวที่คุณชื่นชอบและเปลี่ยนข้อยกเว้นเพื่อส่งคืนรหัสหากคุณต้องการ
/**
* @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);
}
}
นี่คือสิ่งที่ดีที่สุดที่ฉันได้พบ
$sequence1 = $string1; $sequence2 = $string2; $end1 = strlen($string1) - 1; $end2 = strlen($string2) - 1;
ด้วย$sequence1 = preg_split('//u', $string1, -1, PREG_SPLIT_NO_EMPTY); $sequence2 = preg_split('//u', $string2, -1, PREG_SPLIT_NO_EMPTY); $end1 = count($sequence1) - 1; $end2 = count($sequence2) - 1;
สิ่งที่คุณกำลังมองหาคือ "อัลกอริทึมต่าง" การค้นหา google อย่างรวดเร็วทำให้ฉันเข้าสู่โซลูชันนี้ ฉันไม่ได้ทดสอบ แต่อาจจะทำในสิ่งที่คุณต้องการ
พอร์ต php ของ Neil Frasers diff_match_patch (ใบอนุญาต Apache 2.0)
ฉันอยากจะแนะนำดูฟังก์ชั่นที่ยอดเยี่ยมเหล่านี้จากแกน PHP:
Similar_text - คำนวณความคล้ายคลึงกันระหว่างสองสตริง
http://www.php.net/manual/en/function.similar-text.php
levenshtein - คำนวณระยะทาง Levenshtein ระหว่างสองสาย
http://www.php.net/manual/en/function.levenshtein.php
soundex - คำนวณปุ่ม soundex ของสตริง
http://www.php.net/manual/en/function.soundex.php
metaphone - คำนวณคีย์ metaphone ของสตริง
ฉันเจอคลาส PHP diff โดย Chris Boulton จาก Python difflib ซึ่งอาจเป็นทางออกที่ดี: