Unset array Items matching a pattern [duplicate] - php

This question already has answers here:
filter values from an array similar to SQL LIKE '%search%' using PHP
(4 answers)
Closed last month.
I have the following Array :
Array
{
[0]=>"www.abc.com/directory/test";
[1]=>"www.abc.com/test";
[2]=>"www.abc.com/directory/test";
[3]=>"www.abc.com/test";
}
I only want the items that have something in middle in URL like /directory/ and unset the items that do not have that.
Output should be like:
Array
{
[0]=>"www.abc.com/directory/test";
[1]=>"www.abc.com/directory/test";
}

An example without closures. Sometimes you just need to understand the basics first, before you can move on to the neater stuff.
$newArray = array();
foreach($array as $value) {
if ( strpos( $value, '/directory/') ) {
$newArray[] = $value;
}
}

Try using array_filter this:
$result = array_filter($data, function($el) {
$parts = parse_url($el);
return substr_count($parts['path'], '/') > 1;
});
If you have something inside path will allways contain at least 2 slashes.
So for input data
$data = Array(
"http://www.abc.com/directory/test",
"www.abc.com/test",
"www.abc.com/directory/test",
"www.abc.com/test/123"
);
you output will be
Array
(
[0] => http://www.abc.com/directory/test
[2] => www.abc.com/directory/test
[3] => www.abc.com/test/123
)

A couple of approaches:
$urls = array(
'www.abc.com/directory/test',
'www.abc.com/test',
'www.abc.com/foo/directory/test',
'www.abc.com/foo/test',
);
$matches = array();
// if you want /directory/ to appear anywhere:
foreach ($urls as $url) {
if (strpos($url, '/directory/')) {
$matches[] = $url;
}
}
var_dump($matches);
$matches = array();
// if you want /directory/ to be the first path:
foreach ($urls as $url) {
// make the strings valid URLs
if (0 !== strpos($url, 'http://')) {
$url = 'http://' . $url;
}
$parts = parse_url($url);
if (isset($parts['path']) && substr($parts['path'], 0, 11) === '/directory/') {
$matches[] = $url;
}
}
var_dump($matches);

<?php
$array = Array("www.abc.com/directory/test",
"www.abc.com/test",
"www.abc.com/directory/test",
"www.abc.com/test",
);
var_dump($array);
array_walk($array, function($val,$key) use(&$array){
if (!strpos($val, 'directory')) {
unset($array[$key]);
}
});
var_dump($array);
php >= 5.3.0

Related

replace all keys in php array

This is my array:
['apple']['some code']
['beta']['other code']
['cat']['other code 2 ']
how can I replace all the "e" letters with "!" in the key name and keep the values
so that I will get something like that
['appl!']['some code']
['b!ta']['other code']
['cat']['other code 2 ']
I found this but because I don't have the same name for all keys I can't use It
$tags = array_map(function($tag) {
return array(
'name' => $tag['name'],
'value' => $tag['url']
);
}, $tags);
I hope your array looks like this:-
Array
(
[apple] => some code
[beta] => other code
[cat] => other code 2
)
If yes then you can do it like below:-
$next_array = array();
foreach ($array as $key=>$val){
$next_array[str_replace('e','!',$key)] = $val;
}
echo "<pre/>";print_r($next_array);
output:- https://eval.in/780144
You can stick with array_map actually. It is not really practical, but as a prove of concept, this can be done like this:
$array = array_combine(
array_map(function ($key) {
return str_replace('e', '!', $key);
}, array_keys($array)),
$array
);
We use array_keys function to extract keys and feed them to array_map. Then we use array_combine to put keys back to place.
Here is working demo.
Here we are using array_walk and through out the iteration we are replacing e to ! in key and putting the key and value in a new array.
Try this code snippet here
<?php
$firstArray = array('apple'=>'some code','beta'=>'other code','cat'=>'other code 2 ');
$result=array();
array_walk($firstArray, function($value,$key) use (&$result) {
$result[str_replace("e", "!", $key)]=$value;
});
print_r($result);
If you got this :
$firstArray = array('apple'=>'some code','beta'=>'other code','cat'=>'other code 2 ');
You can try this :
$keys = array_keys($firstArray);
$outputArray = array();
$length = count($firstArray);
for($i = 0; $i < $length; $i++)
{
$key = str_replace("e", "!", $keys[ $i ]);
$outputArray[ $key ] = $firstArray[$keys[$i]];
}
We can iterate the array and mark all problematic keys to be changed. Check for the value whether it is string and if so, make sure the replacement is done if needed. If it is an array instead of a string, then call the function recursively for the inner array. When the values are resolved, do the key replacements and remove the bad keys. In your case pass "e" for $old and "!" for $new. (untested)
function replaceKeyValue(&$arr, $old, $new) {
$itemsToRemove = array();
$itemsToAdd = array();
foreach($arr as $key => $value) {
if (strpos($key, $old) !== false) {
$itemsToRemove[]=$key;
$itemsToAdd[]=str_replace($old,$new,$key);
}
if (is_string($value)) {
if (strpos($value, $old) !== false) {
$arr[$key] = str_replace($old, $new, $value);
}
} else if (is_array($value)) {
$arr[$key] = replaceKeyValue($arr[$key], $old, $new);
}
}
for ($index = 0; $index < count($itemsToRemove); $index++) {
$arr[$itemsToAdd[$index]] = $itemsToRemove[$index];
unset($arr[$itemsToRemove[$index]]);
}
return $arr;
}
Another option using just 2 lines of code:
Given:
$array
(
[apple] => some code
[beta] => other code
[cat] => other code 2
)
Do:
$replacedKeys = str_replace('e', '!', array_keys($array));
return array_combine($replacedKeys, $array);
Explanation:
str_replace can take an array and perform the replace on each entry. So..
array_keys will pull out the keys (https://www.php.net/manual/en/function.array-keys.php)
str_replace will perform the replacements (https://www.php.net/manual/en/function.str-replace.php)
array_combine will rebuild the array using the keys from the newly updated keys with the values from the original array (https://www.php.net/manual/en/function.array-combine.php)

php array unique for urls

I need to identify unique urls from an array.
All of the following variants should count as equal:
http://google.com
https://google.com
http://www.google.com
https://www.google.com
www.google.com
google.com
I have the following solution:
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);
}
However, this is not very efficient O(n^2). Can anybody point me to a better solution?
in_array is expensive. Instead of doing that create a hash and store values as their counts.
Something like:
$myHash = []; //a global array to hold values.
And while checking, Do this:
if(!empty($myHash[$needle] )){
//already exits
}
I haven't test it, but maybe something like this will work:
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);
Here is a simplified version. It does not use preg_replace as it costs a lot. Also it does not make any unnecessary string operation.
$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);
Another performance optimization could be implementing binary search on the unique urls because 'in_array' search the whole array as it is not sorted.
<?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);
?>
why you normlize your result array everytime?
here is a better solution with your code:
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));
}
When you want your original items you can use array_keys(array_unique_url($array))
for your normalized urls you don't need array_keys
Try this simplest solution. Here we are using two functions preg_replace and parse_url for achieving desired output
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));

Search for matching partial values in an array [duplicate]

This question already has answers here:
Filter multidimensional array based on partial match of search value
(3 answers)
startsWith() and endsWith() functions in PHP
(34 answers)
Closed 1 year ago.
$target = 285
$array = array("260-315", "285-317", "240-320")
I need to search the array for the value that begins with the $target value. Also, the $target value will not be limited to 3 digits so I'm searching for a match of the digits before the hyphen.
So I want to end up with
$newTarget = 285-317
$finalTarget = 317
Note: I'm only searching for a match of the digits before the hyphen so "200-285" would not be a match
What you asked me in comment(below my answer),for that you can do it like below (My changed answer):-
<?php
$target = 285;
$array = array('260-315', '285-317', '240-320',"200-285");
foreach($array as $key=>$value){
if($target ==explode('-',$value)[0]){
echo $newTarget = $array[$key];
echo PHP_EOL;
echo $finalTarget = explode('-',$array[$key])[1];
}
}
?>
https://eval.in/702862
I can help you filter your array down to members that start with your target.
You can then split the return values to get to your final target.
<?php
$target = '285';
$array = array('260-315', '285-317', '240-320');
$out = array_filter($array, function($val) use ($target) {
return strpos($val, $target) === 0;
});
var_export($out);
Output:
array (
1 => '285-317',
)
<?php
$target = 285;
$arrStack = array(
"260-315",
"285-317",
"240-320",
);
$result = preg_grep('/'.$target.'/',$arrStack);
echo "<pre>"; print_r($result); echo "</pre>";
Something like this could work for you ? array_filter
$target = 285;
$array = array("260-315", "285-317", "240-320");
$newTarget = null;
$finalTarget = null;
$filteredArray = array_filter($array, function($val) use ($target) {
return strpos($val, $target."-") === 0;
});
if(isset($filteredArray[0])){
$newTarget = $filteredArray[0];
$finalTarget = explode($filteredArray[0], "-")[1];
}
Instead of finding what matches, you could exclude what doesn't match with array_filter.
For example:
$target = 285;
$original = array('260-315', '285-317', '240-320');
$final = array_filter($original, function ($value) use ($target) {
// Check if match starts at first character. Have to use absolute check
// because no match returns false
if (stripos($value, $target) === 0) {
return true;
}
return false;
});
The $final array will be a copy of the $original array without the non-matching values.
To output the first digits, you can then loop through your array of matches and get the value before the hyphen:
foreach ($final as $match) {
$parts = explode('-', $match);
if (is_array($parts) && ! empty($parts[0])) {
// Show or do something with value
echo $parts[0];
}
}
Use array_filter:
Example:
$target = '260';
$array = ['260-315', '285-317', '240-320'];
$matches = array_filter($array, function($var) use ($target) { return $target === explode('-', $var)[0]; });
print_r($matches);
Output:
Array
(
[0] => 260-315
)

Help with PHP Array code

Hey guys!
I need some help writing a code that creates an array in the format I needed in. I have this long string of text like this -> "settings=2&options=3&color=3&action=save"...etc Now the next thing I did to make it into an array is the following:
$form_data = explode("&", $form_data);
Ok so far so good...I now have an array like so:
Array
(
[0] => settings=2
[1] => options=3
[2] => color=3
[3] => action=save
)
1
Ok now I need to know how to do two things. First, how can I remove all occurences of "action=save" from the array?
Second, how can I make this array become a key value pair (associative array)? Like "settings=>2"?
Thanks...
There's a function for that. :)
parse_str('settings=2&options=3&color=3&action=save', $arr);
if (isset($arr['action']) && $arr['action'] == 'save') {
unset($arr['action']);
}
print_r($arr);
But just for reference, you could do it manually like this:
$str = 'settings=2&options=3&color=3&action=save';
$arr = array();
foreach (explode('&', $str) as $part) {
list($key, $value) = explode('=', $part, 2);
if ($key == 'action' && $value == 'save') {
continue;
}
$arr[$key] = $value;
}
This is not quite equivalent to parse_str, since key[] keys wouldn't be parsed correctly. I'd be sufficient for your example though.
$str = 'settings=2&options=3&color=3&action=save&action=foo&bar=save';
parse_str($str, $array);
$key = array_search('save', $array);
if($key == 'action') {
unset($array['action']);
}
Ideone Link
This could help on the parsing your array, into key/values
$array; // your array here
$new_array = array();
foreach($array as $key)
{
$val = explode('=',$key);
// could also unset($array['action']) if that's a global index you want removed
// if so, no need to use the if/statement below -
// just the setting of the new_array
if(($val[0] != 'action' && $val[1] != 'save'))$new_array[] = array($val[0]=>$val[1]);
}

php -> delete items from array which contain words from a blacklist

I have got an array with several twitter tweets and want to delete all tweets in this array which contain one of the following words blacklist|blackwords|somemore
who could help me with this case?
Here's a suggestion:
<?php
$banned_words = 'blacklist|blackwords|somemore';
$tweets = array( 'A normal tweet', 'This tweet uses blackwords' );
$blacklist = explode( '|', $banned_words );
// Check each tweet
foreach ( $tweets as $key => $text )
{
// Search the tweet for each banned word
foreach ( $blacklist as $badword )
{
if ( stristr( $text, $badword ) )
{
// Remove the offending tweet from the array
unset( $tweets[$key] );
}
}
}
?>
You can use array_filter() function:
$badwords = ... // initialize badwords array here
function filter($text)
{
global $badwords;
foreach ($badwords as $word) {
return strpos($text, $word) === false;
}
}
$result = array_filter($tweetsArray, "filter");
use array_filter
Check this sample
$tweets = array();
function safe($tweet) {
$badwords = array('foo', 'bar');
foreach ($badwords as $word) {
if (strpos($tweet, $word) !== false) {
// Baaaad
return false;
}
}
// OK
return true;
}
$safe_tweets = array_filter($tweets, 'safe'));
You can do it in a lot of ways, so without more information, I can give this really starting code:
$a = Array(" fafsblacklist hello hello", "white goodbye", "howdy?!!");
$clean = Array();
$blacklist = '/(blacklist|blackwords|somemore)/';
foreach($a as $i) {
if(!preg_match($blacklist, $i)) {
$clean[] = $i;
}
}
var_dump($clean);
Using regular expressions:
preg_grep($array,"/blacklist|blackwords|somemore/",PREG_GREP_INVERT)
But i warn you that this may be inneficient and you must take care of punctuation characters in the blacklist.

Categories