Ortak orta kısmı dize birleştirme

4 Cevap php

Ben iki dizeleri var:

$a = '/srv/http/projects/name';
$b = '/projects/name/some/dir';

Ve ben tekrarlanan değil ortak bir parçası ile birleştirilmiş bir dize almak istiyorum:

$c = '/srv/http/projects/name/some/dir';

Bunu elde etmek için herhangi bir etkili yolu var mı?

4 Cevap

Ben out-of-the-box biliyorum bir şey yok. ama bunu yapmak gerekir:

function merge_overlap($left, $right) {
  // continue checking larger portions of $right
  for($l = 1; $l < strlen($right); $l++) {
    // if we no longer have a matching subsection return what's left appended
    if(strpos($left, substr($right, 0, $l)) === false) {
      return $left . substr($right, $l - 1);
    }
  }

  // no overlap, return all
  return $left . $right;
}

EDIT:. Had bir OBO, güncelleştirilmiş

GÜNCELLEME: Bu strpos () sol yolunda yerde metnin bölümlerini eşleştirme, çözüm değildi, kuyruk karşı karşılaştırmak gerekir.

İşte benim yaklaşımı için doğru bir uygulama:

function merge_overlap($left, $right) {
  $l = strlen($right);
  // keep checking smaller portions of right
  while($l > 0 && substr($left, $l * -1) != substr($right, 0, $l))
    $l--;

  return $left . substr($right, $l);
}

Bu tür çirkin ve dizeleri her zaman '/' ile başlayan varsayar ... ama:

$a = '/srv/http/projects/name';
$b = '/projects/name/some/dir';

$merged = array_merge(explode('/', $a), explode('/', $b) );
$unique = array_unique($merged);

$c = implode('/', $unique);

print $c; // prints "/srv/http/projects/name/some/dir"

Bu deneyin:

function merge($a, $b) {
    // divide into path parts to compare the parts
    $start = preg_split('%/%', $a, -1, PREG_SPLIT_NO_EMPTY);
    $end = preg_split('%/%', $b, -1, PREG_SPLIT_NO_EMPTY);

    // if the first part of the first path is in the second path than switch
    if(in_array($start[0], $end)) {
       $temp = $start;
       $start = $end;
       $end = $temp;
    }
    $parts = array();
    // get the index of the last part of the first path in the second path
    $index = array_search($start[count($start)-1], $end);

    // if the part exists, remove the first parts of the second path
    if($index !== false) {
        $parts = array_merge($start, array_slice($end, $index+1));
    }
    return '/' . join('/', $parts);
}


$a = '/srv/http/projects/name';
$b = '/projects/name/some/dir';

print merge($a, $b);

Bu bana verir:

/srv/http/projects/name/some/dir

Sen yolu ortak bir parçası varsa varsayılan bir değer ya da ne olursa olsun sağlamak zorunda olabilir.

Bunu yapmak için bir "akıllı" bir yolu var sanmıyorum. Sağdaki belirteçleri tüm $b başında belirteçleri aynı sayıda maç kadar sadece $a üzerinde yineleme.

İşte explode() iki dize kolayca array_slice() aracılığıyla belirteçleri doğru sayısını yakalamak böylece.

$a = '/srv/http/projects/name/http';
$b = '/projects/name/http/some/dir';

var_dump(merge_path($a, $b));

function merge_path($path1, $path2)
{
    $p1 = explode('/', trim($path1,' /'));
    $p2 = explode('/', trim($path2,' /'));

    $len = count($p1);

    do
    {
        if (array_slice($p1, -$len) === array_slice($p2, 0, $len))
        {
            return '/'
                 . implode('/', array_slice($p1, 0, -$len))
                 . '/'
                 . implode('/', $p2);
        }
    }
    while (--$len);

    return false;
}