array matching and display in php - php

i am using PHP scripts to implement this...
$keyword=array('local news','art','local','world','tech','entertainment','news','tech','top stories','in the news','front page','bbc news','week in a glance','week in pictures','top stories');
//$keyword has predefined array of strings
$all_meta_tags=get_meta_tags("http://abcnews.go.com/");
$array=$all_meta_tags['keywords'];//store 'keyword' attribute values in $keyword_meta
Now i have to match contents of $array with $keyword.....the results should give me matched items of $array which are present in $keyword
any help plz...?
can array matching/intersection be done case insensitively??
i mean if
$keyword=array('local news');
$array = 'Local News, International News';
var_dump(array_intersect(preg_split('/,\s*/', $array), $keyword));
then it won't match 'Local News'...can you tel me hw to do it if it is possible??

$inBoth = array_intersect(preg_split('/,\s*/', $array), $keyword);
CodePad.
get_meta_tags() just returns the keywords as a string, so we need to split it into an array. We take into account people adding spaces, newlines or tabs after the ,.
You could also skip the regex, and explode on , and then use array_map('trim', $array).
Without doing this, you run the risk of "art" and " art" not matching.
Update
can array matching be done case insensitively?
If you don't mind the resulting arrays being lowercase, you could use array_map('strtolower', $array) on both arrays before using array_intersect().
Otherwise, this will do it...
$metaKeywords = preg_split('/,\s*/', $array);
$matches = array();
foreach($keyword as $keyword) {
foreach($metaKeywords as $value) {
if (strtolower($value) == strtolower($keyword)) {
$matches[] = $keyword;
}
}
}
$matches will have keywords in both arrays case insensitively.
If you have multibyte strings, use mb_strtolower() or equivalent.

You need to use array_intersect()
http://php.net/manual/en/function.array-intersect.php

Related

Replacing values in string

I have a string which contains certain number of #{number} structures. For example:
#328_#918_#1358
SKU:#666:#456
TEST--#888/#982
For each #{number} structure, I have to replace it with a known string.
For the first example:
#328_#918_#1358
I have the following strings:
328="foo"
918="bar"
1358"arg"
And the result should be:
foo_bar_arg
How do I achieve such effect? My current code looks like that:
$matches = array();
$replacements = array();
// starting string
$string = "#328_#918:#1358";
// getting all the numbers from the string
preg_match_all("/\#[0-9]+/", $string, $matches);
// getting rid of #
foreach ($matches[0] as $key => &$feature) {
$feature = preg_replace("/#/", "", $feature);
} // end foreach
// obtaining the replacement values
foreach ($matches[0] as $key => $value) {
$replacement[$value] = "fizz"; // here the value required for replacement is obtained
} // end foreach
But I have no idea how to actually perform a replacement in $string variable using values from $replacement table. Any help is much appreciated!
You can use a preg_replace_callback solution:
$string = '#328_#918:#1358
SKU:#666:#456
TEST--#888/#982';
$replacements = [328=>"foo", 918=>"bar", 1358=>"arg"];
echo preg_replace_callback("/#([0-9]+)/", function ($m) use ($replacements) {
return isset($replacements[$m[1]]) ? $replacements[$m[1]] : $m[0];
}
,$string);
See the PHP demo.
The #([0-9]+) regex will match all non-overlapping occurrences of # and one or more digits right after capturing them into Group 1. If there is an item in the replacements associative array with the numeric key, the whole match is replaced with the corresponding value. Else, the match is returned so that no replacement could occur and the match does not get removed.

How to transform preg_replace to wrap words from an array, instead just one word?

I have the following method, which checks for the word 'example' in a text, and if it finds is, it wraps a span around it:
function highlightWords($dreams) {
$wrap_before = '<span class="highlight_match">';
$wrap_after = '</span>';
$key_words = 'example';
$dreams = json_decode($dreams);
foreach ($dreams as &$value) {
$value->dream = preg_replace("/($key_words)/i",
"$wrap_before$1$wrap_after", $value->dream);
}
return $dreams;
}
I've tried to modify the $key_words variable to an array, so I could give multiple words as parameter, but it always gives back an error. Can I even do this with this approach?
Use implode() to convert your array of keywords into a string that you can use as your regex.
It appears that you want to do a whole word match on one of a number of keywords, so use the alternation operator (the | character) as a delimiter.
For example, given an array of:
$key_words = ['foo', 'bar', 'baz'];
$key_words = implode('|', $key_words);
Yields the following string:
foo|bar|baz
Which you can then use in place to create your regex of key words:
// /(foo|bar|baz)/i
preg_replace("/($key_words)/i",
"$wrap_before$1$wrap_after", $value->dream);
Hope this helps :)

regular expression word preceded by char

I want to grab a specific string only if a certain word is followed by a = sign.
Also, I want to get all the info after that = sign until a / is reached or the string ends.
Let's take into example:
somestring.bla/test=123/ohboy/item/item=capture
I want to get item=capture but not item alone.
I was thinking about using lookaheads but I'm not sure it this is the way to go. I appreciate any help as I'm trying to grasp more and more about regular expressions.
[^/=]*=[^/]*
will give you all the pairs that match your requirements.
So from your example it should return:
test=123
item=capture
Refiddle Demo
If you want to capture item=capture, it is straightforward:
/item=[^\/]*/
If you want to also extract the value,
/item=([^\/]*)/
If you only want to match the value, then you need to use a look-behind.
/(?<=item=)[^\/]*/
EDIT: too many errors due to insomnia. Also, screw PHP and its failure to disregard separators in a character group as separators.
Here is a function I wrote some time ago. I modified it a little, and added the $keys argument so that you can specify valid keys:
function getKeyValue($string, Array $keys = null) {
$keys = (empty($keys) ? '[\w\d]+' : implode('|', $keys));
$pattern = "/(?<=\/|$)(?P<key>{$keys})\s*=\s*(?P<value>.+?)(?=\/|$)/";
preg_match_all($pattern, $string, $matches, PREG_SET_ORDER);
foreach ($matches as & $match) {
foreach ($match as $key => $value) {
if (is_int($key)) {
unset($match[$key]);
}
}
}
return $matches ?: FALSE;
}
Just trow in the string and valid keys:
$string = 'somestring.bla/test=123/ohboy/item/item=capture';
$keys = array('test', 'item');
$keyValuePairs = getKeyValue($string, $keys);
var_dump($keyValuePairs);

A more forgiving array_intersect in PHP

array_intersect takes two arrays and looks for matching === values and returns the result. However the values in the array have to match character for character. Is there a function or a method for comparing two arrays and looking for values that contain similar strings instead of equal similar strings. Something like stripos but with array_intersect.
$array1 = array("howdyhorse", "monkeyjoe", "bill", "donkeymonkey", "carrothorse")
$array2 = array("bill", "horse", "monkeybunk", "apple", "panda")
function($array1, $array2);
Returns an array = array("bill", "horse", "monkeyjoe")
The order is of no particular concern.
Is running all the values of each array through something like
foreach( $array as $slice )
$slice = trim( preg_replace( $pattern, $replacement ) ) ;
to make everything lowercase and remove spaces and special chars and then doing an array_intersect an option?
You could use array_uintersect and similar_text. similar_text is O(N**3), so you need to write your own function if your compare similar logic is simpler.

A bit lost with preg_match regular expression

I'm a beginner in regular expression so it didn't take long for me to get totally lost :]
What I need to do:
I've got a string of values 'a:b,a2:b2,a3:b3,a4:b4' where I need to search for a specific pair of values (ie: a2:b2) by the second value of the pair given (b2) and get the first value of the pair as an output (a2).
All characters are allowed (except ',' which seperates each pair of values) and any of the second values (b,b2,b3,b4) is unique (cant be present more than once in the string)
Let me show a better example as the previous may not be clear:
This is a string: 2 minutes:2,5 minutes:5,10 minutes:10,15 minutes:15,never:0
Searched pattern is: 5
I thought, the best way was to use function called preg_match with subpattern feature.
So I tried the following:
$str = '2 minutes:2,5 minutes:5,10 minutes:10,15 minutes:15,20 minutes:20,30 minutes:30, never:0';
$re = '/(?P<name>\w+):5$/';
preg_match($re, $str, $matches);
echo $matches['name'];
Wanted output was '5 minutes' but it didn't work.
I would also like to stick with Perl-Compatible reg. expressions as the code above is included in a PHP script.
Can anyone help me out? I'm getting a little bit desperate now, as Ive spent on this most of the day by now ...
Thanks to all of you guys.
$str = '2 minutes:2,51 seconds:51,5 minutes:5,10 minutes:10,15 minutes:51,never:0';
$search = 5;
preg_match("~([^,\:]+?)\:".preg_quote($search)."(?:,|$)~", $str, $m);
echo '<pre>'; print_r($m); echo '</pre>';
Output:
Array
(
[0] => 5 minutes:5
[1] => 5 minutes
)
$re = '/(?:^|,)(?P<name>[^:]*):5(?:,|$)/';
Besides the problem of your expression having to match $ after 5, which would only work if 5 were the last element, you also want to make sure that after 5 either nothing comes or another pair comes; that before the first element of the pair comes either another element or the beginning of the string, and you want to match more than \w in the first element of the pair.
A preg_match call will be shorter for certain, but I think I wouldn't bother with regular expressions, and instead just use string and array manipulations.
$pairstring = '2 minutes:2,5 minutes:5,10 minutes:10,15 minutes:15,20 minutes:20,30 minutes:30, never:0';
function match_pair($searchval, $pairstring) {
$pairs = explode(",", $str);
foreach ($pairs as $pair) {
$each = explode(":", $pair);
if ($each[1] == $searchval) {
echo $each[0];
}
}
}
// Call as:
match_pair(5, $pairstring);
Almost the same as #Michael's. It doesn't search for an element but constructs an array of the string. You say that values are unique so they are used as keys in my array:
$str = '2 minutes:2,5 minutes:5,10 minutes:10,15 minutes:15,20 minutes:20,30 minutes:30, never:0';
$a = array();
foreach(explode(',', $str) as $elem){
list($key, $val) = explode(':', $elem);
$a[$val] = $key;
}
Then accessing an element is very simple:
echo $a[5];

Categories