~ 300.000 girişleri ve çıkış farklılıkları ile iki büyük metin dosyaları karşılaştırmak için PHP kodu

6 Cevap php

i've got two lists A and B, B = A + C - D. All elements are unique, no duplicates. How do i get the lists of:
(1) the new items added, C
(2) the old items removed, D

C and D aren't more than 10000 elements or so.

Edit

Bok, üzgünüm beyler - önemli detay unuttum - bu değil bellek elemanlarında hem metin dosyalarıdır.

6 Cevap

Sen zaten iki dosya A ve B var dedi

Burada bir Unix sisteminde çalışan varsayarak en kolay, en hızlı çözüm.

system("comm -13 A B > C");
system("comm -23 A B > D");

//read C and D in PHP

Ben gerçekten bu işlem yani, zaman birimi başına infaz belirli bir sayıda gidiyoruz olacak nasıl ölçülebilir odaklanmak istediğiniz sürece dizilerin boyutu alakasız olduğunu düşünüyorum.

Sadece onu halletmek için bunu yapmak gerekiyorsa, bunu kullanarak benim için oldukça önemsiz görünüyor array_diff()

$a = array( 1, 2, 3, 4 );
$b = array( 1, 3, 5, 7 ); // 2 and 4 removed, 5 and 7 added

$c = array_diff( $b, $a ); // [5, 7]
$d = array_diff( $a, $b ); // [2, 4]

Bunu yapmanın en etkili yolu, ilk önce sıralama listeleri ve mümkün olduğunca birkaç kez olarak dizinin elemanlarına erişim olacaktır. Örnek:

<?php

sort($a, SORT_NUMERIC);
sort($b, SORT_NUMERIC);
$c = array();
$d = array();
while (($currA = array_pop($a)) !== null) {
        while (($currB = array_pop($b)) !== null) {
                if ($currB == $currA) {
                        // exists in both, skip value
                        continue 2;
                }
                if ($currA > $currB) {
                        // exists in A only, add to D, push B back on to stack
                        $d[] = $currA;
                        $b[] = $currB;
                        continue 2;
                }
                // exists in B only, add to C
                $c[] = $currB;
        }
        // exists in A only, for values of A < all of B
        $d[] = $currA;
}

Bu uzun sadece bir kaç yüz unsurlardır listeleri için hızlı 2 aramalar bile array_diff daha büyüklükte siparişleri gerçekleştirmek için gidiyor.

fonksiyonu diffLists ($ listA, $ ListB) {

  $resultAdded = array();
  $resultRemoved = array();
  foreach($listB AS $item) {
    if (!in_array($item,$listA)) {
       $resultAdded[] = $item;
    }
  }
  foreach($listA AS $item) {
    if (!in_array($item,$listB)) {
      $resultRemoved[] = $item;
    }
  }
  return array($resultAdded,$resultRemoved);
}



$myListA = array('item1','item2','item3');
$myListB = array('item1','item3','item4');
print_r(diffLists($myListA,$myListB));

Bu çıkış 2 elemanlı bir dizi gerekir. İlk öğe liste B EKLENDİ ve ikinci eleman liste B'de çıkarıldı öğelerin bir listesi öğelerin bir listesi

Sen, daha verimli bu istiyorsanız Levenshtein algoritma denemek isteyebilirsiniz

http://en.wikipedia.org/wiki/Levenshtein_distance

Her B A değeri (ve tersi) arıyor O (n ^ 2) karmaşıklığı vardır.

Büyük miktarda veri için, (n log n), daha sonra eklenen / kaldırılan elemanlarını hesaplarken sıralanmış listeleri tek bir geçiş yapmak listeleri O her sıralamak için muhtemelen daha iyi. (Biliyorsunuz beri yapmak nispeten kolay hiçbir çiftleri vardır.)