Get URLs lowest path by domain - php

I have an array that looks like the following...
$urls = array(
"http://www.google.com",
"http://www.google.com/maps",
"http://www.google.com/mail",
"https://drive.google.com/help",
"https://www.youtube.com",
"https://www.youtube.com/feed/subscriptions",
"https://www.facebook.com/me",
"https://www.facebook.com/me/friends"
);
I find this hard to explain but I want to break this array down to only show the lowest path for each domain with no duplicates, so it looks like this...
$urls = array(
"http://www.google.com",
"https://drive.google.com/help",
"https://www.youtube.com",
"https://www.facebook.com/me"
);

This can be achieved by walking through the array and inspecting the host key by using parse_url(). The following logic will give your desired result.
$output = array();
//Sort the array by character length
usort($urls, function($a, $b) {
return strlen($a)-strlen($b);
});
array_walk($urls, function($url) use (&$output) {
//Parse the URL to get its components
$parsed_url = parse_url($url);
//See if we've already added the host to our final array
if( array_key_exists($parsed_url['host'], $output) === FALSE ) {
//We haven't, so we can now add the url to our final array
$output[$parsed_url['host']] = $url;
}
});
https://eval.in/415655

try this,
$urls = array(
"http://www.google.com",
"http://www.google.com/maps",
"http://www.google.com/mail",
"https://drive.google.com/help",
"https://www.youtube.com",
"https://www.youtube.com/feed/subscriptions",
"https://www.facebook.com/me",
"https://www.facebook.com/me/friends"
);
$temp = array();
$res = array();
usort($urls, function($a, $b) {
return strlen($a)-strlen($b);
});//sort the array based string length
foreach($urls as $url){
$str = preg_replace('#^https?://#', '', $url);
$strarray = explode("/", $str);
if(!in_array($strarray[0], $temp)){
$temp[] = $strarray[0];
$res[] = $url;
}
}
echo"<pre>";
print_r($res);
echo"</pre>";
output:
Array
(
[0] => http://www.google.com
[1] => https://www.youtube.com
[2] => https://www.facebook.com/me
[3] => https://drive.google.com/help
)

Related

How to get an associative array from a string?

This is the initial string:-
NAME=Marco\nLOCATION=localhost\nSECRET=fjsdgfsjfdskffuv=\n
This is my solution although the "=" in the end of the string does not appear in the array
$env = file_get_contents(base_path() . '/.env');
// Split string on every " " and write into array
$env = preg_split('/\s+/', $env);
//create new array to push data in the foreach
$newArray = array();
foreach($env as $val){
// Split string on every "=" and write into array
$result = preg_split ('/=/', $val);
if($result[0] && $result[1])
{
$newArray[$result[0]] = $result[1];
}
}
print_r($newArray);
This is the result I get:
Array ( [Name] => Marco [LOCATION] => localhost [SECRET] => fjsdgfsjfdskffuv )
But I need :
Array ( [Name] => Marco [LOCATION] => localhost [SECRET] => fjsdgfsjfdskffuv= )
You can use the limit parameter of preg_split to make it only split the string once
http://php.net/manual/en/function.preg-split.php
you should change
$result = preg_split ('/=/', $val);
to
$result = preg_split ('/=/', $val, 2);
Hope this helps
$string = 'NAME=Marco\nLOCATION=localhost\nSECRET=fjsdgfsjfdskffuv=\n';
$strXlate = [ 'NAME=' => '"NAME":"' ,
'LOCATION=' => '","LOCATION":"',
'SECRET=' => '","SECRET":"' ,
'\n' => '' ];
$jsonified = '{'.strtr($string, $strXlate).'"}';
$array = json_decode($jsonified, true);
This is based on 1) translation using strtr(), preparing an array in json format and then using a json_decode which blows it up nicely into an array...
Same result, other approach...
You can also use parse_str to parse URL syntax-like strings to name-value pairs.
Based on your example:
$newArray = [];
$str = file_get_contents(base_path() . '/.env');
$env = explode("\n", $str);
array_walk(
$env,
function ($i) use (&$newArray) {
if (!$i) { return; }
$tmp = [];
parse_str($i, $tmp);
$newArray[] = $tmp;
}
);
var_dump($newArray);
Of course, you need to put some sanity check in the function since it can insert some strange stuff in the array like values with empty string keys, and whatnot.

Group together array elements

I have an array in PHP:-
$arr = ["BX_NAME0","BX_NAME1","BX_NAME2","BX_categoryName0","BX_categoryName1","BX_categoryName2","BHA_categories0","BHA_categories1","BHA_categories2"]
Here I want to group together elements based on same ending integer together in json like
$post_data = array(
'0' => array(
'BX_NAME0' => $item_type,
'BX_categoryName0' => $string_key,
'BHA_categories0' => $string_value
),
'1' => array(
'BX_NAME1' => $item_type,
'BX_categoryName1' => $string_key,
'BHA_categories1' => $string_value
),
);
I have Used:- filter_var($key , FILTER_SANITIZE_NUMBER_INT);
to get the integer part of the array elements but don't known how to group them further.
You can do it like below using preg_match():-
$new_array = array();
foreach ($arr as $ar){
preg_match_all('!\d+!', $ar, $matches); //get the number from string
$new_array[$matches[0][0]][$ar] = '';
}
echo "<pre/>";print_r($new_array);
Output:- https://eval.in/715548
It should be something like this:-
$arr = array("BX_NAME0","BX_NAME1","BX_NAME2","BX_categoryName0","BX_categoryName1","BX_categoryName2","BHA_categories0","BHA_categories1","BHA_categories2");
$post_data = array();
foreach($arr as $value) {
$key = filter_var($value , FILTER_SANITIZE_NUMBER_INT);
if(isset($post_data[$key]) && !is_array($post_data[$key])) {
$post_data[$key] = array();
}
$post_data[$key][] = $value;
}
print_r($post_data);
Tested and works
However, I suggest you use substr() to get the last character of the array item, for performance and stuff..
By using filter_var() method
$arr = ["BX_NAME0","BX_NAME1","BX_NAME2","BX_categoryName0","BX_categoryName1","BX_categoryName2","BHA_categories0","BHA_categories1","BHA_categories2"];
foreach($arr as $a){
$int = filter_var($a, FILTER_SANITIZE_NUMBER_INT);
$newarr[$int][$a] = '';
}
print_r($newarr);
Output:-https://eval.in/715581

Reduce URL strings with no duplicates

I have an array that looks like the following...
$urls = array(
"http://www.google.com",
"http://www.google.com/maps",
"http://www.google.com/mail",
"https://drive.google.com",
"https://www.youtube.com",
"https://www.youtube.com/feed/subscriptions",
"https://www.facebook.com/me",
"https://www.facebook.com/me/friends"
);
I find this hard to explain but I want to break this array down to only show the reduced URLs with no duplicates, so it looks like this...
$urls = array(
"http://www.google.com",
"https://drive.google.com",
"https://www.youtube.com",
"https://www.facebook.com/me"
);
Notice the last URL in the second array still has it's path. This is because I want still want to show the lowest level paths
Based on #Tim's answer
foreach ($urls as &$url) {
$url_parts = parse_url($url);
$url = $url_parts["scheme"]."://".$url_parts["host"];
}
$urls = array_unique($urls);
Just sort the array in reverse order, and create an array indexed by host:
$urls = array(
"http://www.google.com",
"http://www.google.com/maps",
"http://www.google.com/mail",
"https://drive.google.com",
"https://www.youtube.com",
"https://www.youtube.com/feed/subscriptions",
"https://www.facebook.com/me",
"https://www.facebook.com/me/friends"
);
rsort($urls);
$return = [];
foreach($urls as $url) {
$host = parse_url($url, PHP_URL_HOST);
$return[$host] = $url;
}
$return = array_values($return); // To remove array keys, if desired.
The reverse-ordered urls array would be:
Array
(
[0] => https://www.youtube.com/feed/subscriptions
[1] => https://www.youtube.com
[2] => https://www.facebook.com/me/friends
[3] => https://www.facebook.com/me
[4] => https://drive.google.com
[5] => http://www.google.com/maps
[6] => http://www.google.com/mail
[7] => http://www.google.com
)
Since the last entry (per host name) in the sorted array is the one that you want, and it deliberately clobbers any existing array value, this would output:
Array
(
[www.youtube.com] => https://www.youtube.com
[www.facebook.com] => https://www.facebook.com/me
[drive.google.com] => https://drive.google.com
[www.google.com] => http://www.google.com
)
Try this:
$result = array();
array_push($result, $urls[0])
for($i=1; $i<count($urls); $i++)
{
$repeat = false;
foreach($result as $res)
{
if(strpos($urls[i], $res))
{
$repeat = true;
break;
}
}
if(!repeat)
array_push($result, $urls[i])
}
return $result;

PHP, Combining each array item to the previous ones

I am building breadcrumbs and I would like to do it from all segments from the current url.
I am getting the array that looks like this
$segments = [0 =>'users',
1 =>'index',
2 =>'all'];
I'd like to combine the array in this way :
$routes = [ 0 =>'users',
1 =>'users/index',
2 =>'users/index/all'];
I have tried using array_map
$segs = array_map(function($a){return $a."/".$a;},$segments);
but it combines the same array item twice
Any help is appreciated.
This should work for you:
Just loop through each element and take an array_slice() from the start until the current element, which you then simply can implode() with a slash.
<?php
$segments = ["users", "index", "all"];
foreach($segments as $k => $v)
$result[] = implode("/", array_slice($segments, 0, ($k+1)));
print_r($result);
?>
output:
Array
(
[0] => users
[1] => users/index
[2] => users/index/all
)
If you want to do it using array_map() same as #Rizier123's method,
$segments = ['users','index','all'];
$routes = array_map(function($v, $k) use ($segments){
return implode('/', array_slice($segments, 0, ($k+1)));
}, $segments, array_keys($segments));
Use this code to fix this issue :
$arr = array(0 =>'users', 1 =>'index', 2 =>'all');
print_r(returnPath($arr));
function returnPath($urlArr = null){
$index = 1; $sep='';
$length = count($urlArr);
foreach($urlArr as $key => $item){
if($index > 1 && $index < $length){ $sep = '/'; }
$temp .= $sep.$item;
$urlArr[$key] = $temp;
$index++;
}
return $urlArr;
}
To avoid slicing and imploding on every iteration, you can concatenate and ltrim instead.
Code: (Demo)
$segments = ["users", "index", "all"];
var_export(
array_map(
function($v) {
static $path = '';
return ltrim($path .= "/$v", '/');
},
$segments
)
);
Output:
array (
0 => 'users',
1 => 'users/index',
2 => 'users/index/all',
)

Parsing complex URLs

I try to parse a list of url strings, after two hours of work I don't reach any result, the list of url strings look like this:
$url_list = array(
'http://google.com',
'http://localhost:8080/test/project/',
'http://mail.yahoo.com',
'http://www.bing.com',
'http://www.phpromania.net/forum/viewtopic.php?f=24&t=7549',
'https://prodgame10.alliances.commandandconquer.com/12/index.aspx',
'https://prodgame10.alliances.commandandconquer.ro/12/index.aspx',
);
Output should be:
Array
(
[0] => .google.com
[1] => .localhost
[2] => .yahoo.com
[3] => .bing.com
[4] => .phpromania.net
[5] => .commandandconquer.com
)
The first thing what induce me in the error zone is more than 2 dots in the url.
Any algorithm example?
This is what I try:
$url_list = array(
'http://google.com',
'http://localhost:8080/test/project/',
'http://mail.yahoo.com',
'http://www.bing.com',
'http://www.phpromania.net/forum/viewtopic.php?f=24&t=27549',
'https://prodgame10.alliances.commandandconquer.com/12/index.aspx',
);
function size($list)
{
$i=0;
while($list[++$i]!=NULL);
return $i;
}
function url_Host($list)
{
$listSize = size($list)-1;
do
{
$strSize = size($list[$listSize]);
$points = 0;
$dpoints = 0;
$tmpString = '';
do
{
$currentChar = $list[$listSize][$strSize];
if(ord('.')==ord($currentChar))
{
$tmpString .= '.';
$points++;
}
else if(ord(':')==ord($currentChar))
{
$tmpString .= ':';
$dpoints++;
}
}while($list[$listSize][--$strSize]!=NULL);
print $tmpString;
$strSize = size($list[$listSize]);
$tmpString = '';
do
{
$slice = false;
$currentChar = $list[$listSize][$strSize];
if($dpoints > 2)
{
if(ord('\\')==ord($curentChar)) $slice = true;
$tmpString .= '';
}
}while($list[$listSize][--$strSize]!=NULL);
print $tmpString."<br />";
}while($list[--$listSize]);
}
url_Host($url_list);
You can use the built-in function parse_url() as follows:
function getDomain($url)
{
$domain = implode('.', array_slice(explode('.', parse_url($url, PHP_URL_HOST)), -2));
return $domain;
}
Test cases:
foreach ($url_list as $url) {
$result[] = getDomain($url);
}
Output:
Array
(
[0] => google.com
[1] => localhost
[2] => yahoo.com
[3] => bing.com
[4] => phpromania.net
[5] => commandandconquer.com
[6] => commandandconquer.ro
)
As for the dots, you can manually prepend them to string, like so:
$result[] = "." . getDomain($url);
I'm not sure why you need to do this, but this should work.
Demo!
Look at parse_url. For example:
$url = 'http://www.phpromania.net/forum/viewtopic.php?f=24&t=7549';
$host = parse_url($url, PHP_URL_HOST);
First the result for localhost is no sense, but try this:
$result =array();
foreach($url_list as $u){
$arr = explode('//',$u);
$arr2 = explode('.', $arr[1]);
if($arr2[0] == 'www')
array_push($result, $arr2[1]);
else
array_push($result, $arr2[0]);
}
We can also use array_map() with an arrow function to simplify the code.
I'm refactoring #Alessandro Minoccheri's code here.
$domains = array_map(fn($url) => implode('.', array_slice(explode('.', parse_url($url, PHP_URL_HOST)), -2)),$urls);
var_dump($domains);

Categories