代码之家  ›  专栏  ›  技术社区  ›  hsz

将字符串与公共中间部分合并

  •  3
  • hsz  · 技术社区  · 15 年前

    我有两条线:

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

    我想得到一个没有重复公共部分的合并字符串:

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

    有什么有效的方法可以得到它吗?

    5 回复  |  直到 15 年前
        1
  •  1
  •   nortron    15 年前

    从盒子里我什么都不知道。 但这应该做到:

    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;
    }
    

    编辑:有一个海外建筑运营管理局,更新。

    更新:这不是解决方案,strpos()在左路径的任何位置匹配文本的部分,应该与tail进行比较。

    以下是我的方法的正确实现:

    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);
    }
    
        2
  •  1
  •   Owen Ryan Doherty    15 年前

    它有点难看,并且假设您的字符串总是以“/”开头。但是:

    $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"
    
        3
  •  1
  •   Adelf    15 年前
    
    function f($a, $b)
    {
      for($i=0; count($a) > $i ; $i++)
      {
        if(strpos($b, substr($a, $i)) !== FALSE)
          return substr($a, 0, $i-1).$b;
      } 
      return $a.$b;
    }
    
        4
  •  0
  •   Felix Kling    15 年前

    试试这个:

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

    这给了我:

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

    如果路径没有公共部分,则可能必须提供默认值或其他值。

        5
  •  0
  •   Josh Davis    15 年前

    我认为没有一种“聪明”的方法可以做到这一点。只是重复一遍 $a 直到所有最右边的令牌在 $b .

    这里我 explode() 两个字符串,以便我可以通过 array_slice() .

    $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;
    }