【问题标题】:php array unique for urlsurl 唯一的 php 数组
【发布时间】:2017-05-05 10:29:30
【问题描述】:

我需要从数组中识别unique urls

以下所有变体应视为相同:

http://google.com
https://google.com
http://www.google.com
https://www.google.com
www.google.com
google.com

我有以下解决方案:

public static function array_unique_url(array $array) : array
{
    $uniqueArray = [];
    foreach($array as $item) {
        if(!self::in_array_url($item, $uniqueArray)){
            $uniqueArray[] = $item;
        }
    }
    return $uniqueArray;
}

public static function in_array_url(string $needle, array $haystack): bool {
    $haystack = array_map([self::class, 'normalizeUrl'], $haystack);
    $needle = self::normalizeUrl($needle);

    return in_array($needle, $haystack);
}

public static function normalizeUrl(string $url) {
    $url = strtolower($url);
    return preg_replace('#^(https?://)?(www.)?#', '', $url);
}

但是,这不是非常有效的 O(n^2)。谁能指出一个更好的解决方案?

【问题讨论】:

  • 你能解释一下你的问题吗?
  • @SahilGulati 我认为这很清楚。人们理解这个问题

标签: php arrays regex array-unique


【解决方案1】:

in_array 很昂贵。而不是这样做创建一个哈希并将值存储为它们的计数。 比如:

$myHash = []; //a global array to hold values.

在检查时,这样做:

if(!empty($myHash[$needle] )){
   //already exits
}

【讨论】:

    【解决方案2】:

    我还没有测试过,但也许这样的东西会起作用:

    function getUniqueUrls(array $urls)
    {
        $unique_urls = [];
        foreach ($urls as $url) {
            $normalized_url = preg_replace('#^(https?://)?(www.)?#', '', strtolower($url));
            $unique_urls[$normalized_url] = true;
        }
    
        return array_keys($unique_urls);
    }
    
    $arr = [
        'http://google.com',
        'https://google.com',
        'http://www.google.com',
        'https://www.google.com',
        'www.google.com',
        'google.com'
    ];
    
    $unique_urls = getUniqueUrls($arr);
    

    【讨论】:

      【解决方案3】:

      这是一个简化版本。它不使用 preg_replace 因为它花费很多。它也不会进行任何不必要的字符串操作。

      $urls = array(
          "http://google.com",
          "https://google.com",
          "http://www.google.com",
          "https://www.google.com",
          "www.google.com",
          "google.com"
      );
      
      $uniqueUrls = array();
      
      foreach($urls as $url) {
          $subPos = 0;
          if(($pos = stripos($url, "://")) !== false) {
              $subPos = $pos + 3;
          }
          if(($pos = stripos($url, "www.", $subPos)) !== false) {
              $subPos = $pos + 4;
          }
          $subStr = strtolower(substr($url, $subPos));
          if(!in_array($subStr, $uniqueUrls)) {
              $uniqueUrls[] = $subStr;
          }
      }
      
      var_dump($uniqueUrls);
      

      另一个性能优化可能是对唯一 url 实现二进制搜索,因为 'in_array' 搜索整个数组,因为它没有排序。

      【讨论】:

        【解决方案4】:
        <?php 
        
        $urls = [
            'http://google.com',
            'https://google.com',
            'http://www.google.com',
            'https://www.google.com',
            'www.google.com',
            'google.com',
            'testing.com:9200'
        ];
        
        $uniqueUrls = [];
        
        foreach ($urls as $url) {
            $urlData = parse_url($url);
            $urlHostName = array_key_exists('host',$urlData) ? $urlData['host'] : $urlData['path'];
            $host = str_replace('www.', '', $urlHostName);
            if(!in_array($host, $uniqueUrls) && $host != ''){
                array_push($uniqueUrls, $host);
            }
        }
        print_r($uniqueUrls);
        
        ?>
        

        【讨论】:

          【解决方案5】:

          为什么你每次都标准化你的结果数组?

          这是一个更好的代码解决方案:

          public static function array_unique_url(array $array): array
          {
              $uniqueArray = [];
              foreach ($array as $item) {
                  if (!isset($uniqueArray[$item])) {
                      $uniqueArray[$item] = self::normalizeUrl($item);
                  }
              }
          
              return $uniqueArray;
          }
          
          public static function normalizeUrl(string $url)
          {
              return preg_replace('#^(https?://)?(www.)?#', '', strtolower($url));
          }
          

          当你想要你的原始物品时,你可以使用array_keys(array_unique_url($array))

          对于您不需要array_keys的标准化网址

          【讨论】:

            【解决方案6】:

            试试这个最简单的解决方案。这里我们使用两个函数preg_replaceparse_url 来实现所需的输出

            Try this code snippet here

            <?php
            
            $urls = array(
                "http://google.com",
                "https://google.com",
                "http://www.google.com",
                "https://www.google.com",
                "www.google.com",
                "google.com"
            );
            
            $uniqueUrls=array();
            foreach($urls as $url)
            {
                $changedUrl=  preg_replace("/^(https?:\/\/)?/", "http://", $url);//adding http to urls which does not contains.
                $domain=  preg_replace("/^(www\.)?/","",parse_url($changedUrl,PHP_URL_HOST));//getting the desired host and then removing its www.
                preg_match("/^[a-zA-Z0-9]+/", $domain,$matches);//filtering on the basis of domains
                $uniqueUrls[$matches[0]]=$domain;
            }
            print_r(array_values($uniqueUrls));
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-04-05
              • 2019-07-26
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多