2017-05-05 24 views
-1

我需要从数组中识别unique urlsphp array对于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)。任何人都可以指出我更好的解决方案吗?

+0

你能解释一下你的问题一次? –

+0

@SahilGulati我认为这很清楚。人们理解这个问题 – Chris

回答

1

in_array是昂贵的。而不是这样做创建一个散列和存储值作为他们的计数。 喜欢的东西:

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

虽然检查,这样做:

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

我没有测试它,但也许这样的事情会工作:

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

这里是一个简化版本。它不使用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”搜索整个阵列,因为它是没有排序。

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

?> 
0

为什么你每次都调整结果数组?

这里是你的代码更好的解决方案:

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

0

试试这个最简单的解决方案这里我们使用两个函数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));