php preg match. Find elements with two values not in order - php

I got array like:
$array = array(
3A32,
4565,
7890,
0012,
A324,
9002,
3200,
345A,
0436
);
Then I need to find which elements has two numbers. The value of number can change.
If values were:
$n1 = 0;
$n2 = 3;
For that search preg_match() should return (3200,0436)
If values were:
$n1 = 0;
$n2 = 0;
preg_match() should return (0012,3200,9002)
Any idea?
Thanks.

I got your logic after looking multiple times on your input array as well as output based on given numbers.
Since i am not good in regular expression at all, i will go to find out answer with commonly know PHP functions.
1.Create a function which takes initial array as well as those search numbers in array form (so that you can search any number and any length of numbers).
2.Now iterate over initial array, split each value to convert to array and do array_count_value() for both split array and numbers array. now apply check and see exact match found or not?
3.Assign this match to a new array declared under the function itself.
4.Return this array at the end of function.
$n1 = 0;
$n2 = 0;
function checkValues($array,$numbers=array()){
$finalArray = [];
if(!empty($numbers)){
foreach($array as $arr){
$splitArr = str_split($arr);
$matched = true;
$count_number_Array = array_count_values($numbers);
$count_split_array = array_count_values($splitArr);
foreach($count_number_Array as $key=>$value){
if(!isset($count_split_array[$key]) || $count_split_array[$key] < $value){
$matched = false;
break;
}
}
if($matched === true){
$finalArray[] = $arr;
}
}
}
return $finalArray;
}
print_r(checkValues($array, array($n1,$n2)));
Output: https://3v4l.org/7uWfC And https://3v4l.org/Tuu5m And https://3v4l.org/fEKTO

Instead of using preg_match, you might use preg_grep and dynamically create a pattern that will match the 2 values in each order using an alternation.
^[A-Z0-9]*0[A-Z0-9]*3[A-Z0-9]*|[A-Z0-9]*3[A-Z0-9]*0[A-Z0-9]*$
The character class [A-Z0-9] matches either a char A-Z or a digit 0-9.
Regex demo | Php demo
If you want to use other characters, you could also take a look at preg_quote to handle regular expression characters.
function getElementWithTwoValues($n1, $n2) {
$pattern = "/^[A-Z0-9]*{$n1}[A-Z0-9]*{$n2}[A-Z0-9]*|[A-Z0-9]*{$n2}[A-Z0-9]*{$n1}[A-Z0-9]*$/";
$array = array(
"3A32",
"4565",
"7890",
"0012",
"A324",
"9002",
"3200",
"345A",
"0436"
);
return preg_grep($pattern, $array);
}
print_r(getElementWithTwoValues(0, 3));
print_r(getElementWithTwoValues(0, 0));
Output
Array
(
[6] => 3200
[8] => 0436
)
Array
(
[3] => 0012
[5] => 9002
[6] => 3200
)

Related

Transform every two array items into associative array pairs

I'm trying to make an associative array from my string, but nothing works and I don't know where the problem is.
My string looks like:
$string = "somethink;452;otherthink;4554;somethinkelse;4514"
I would like to make an associative array, where "text" is the key, and the number is value.
Somethink => 452 otherthink => 4554 Somethinkelse => 4514
I tried to convert the string into an array and then to the associative array but it's not working. I decided to use:
$array=explode(";",$string);
Then tried to use a foreach loop but it's not working. Can somebody help?
Using regex and array_combine:
$string = "somethink;452;otherthink;4554;somethinkelse;4514";
preg_match_all("'([A-Za-z]+);(\d+)'", $string, $matches);
$assoc = array_combine($matches[1], $matches[2]);
print_r($assoc);
Using a traditional for loop:
$string = "somethink;452;otherthink;4554;somethinkelse;4514";
$arr = explode(";", $string);
for ($i = 0; $i < count($arr); $i += 2) {
$assoc[$arr[$i]] = $arr[$i+1];
}
print_r($assoc);
Result:
Array
(
[somethink] => 452
[otherthink] => 4554
[somethinkelse] => 4514
)
Note that there must be an even number of pairs; you can add a condition to test this and use a substitute value for any missing keys, or omit them.

How to output an array starting from the value with the highest character match count in php

I have been trying to match a string with the values in an array and output the array strings starting from the string with the highest character match count. for example:
$array = array(
'mike'=>'book21',
'ben'=>'buzz',
'jack'=>'airdrone',
'july'=>'march',
'fred'=>'blend45'
);
$string = 'blenmaio2';
As you can see, 'blend45', has the highest matched characters, with a total of 4 matched characters. I want to be able to output them starting from the first four highest match count, here is an example of the output i want:
blend45
book21
march
buzz
This is my first time trying to help someone, so hopefully this does the trick. I know you can probably simplify the code a little, but this is what I have.
<?php
$array = array(
'mike'=>'book21',
'ben'=>'buzz',
'jack'=>'airdrone',
'july'=>'march',
'fred'=>'blend45'
);
$string = 'blenmaio2';
$sort_array=array(); //Empty array
foreach ($array as $key => $value){
$num = similar_text($value,$string); //Using similar text to compar the strings.
$sort_array[$value] = $num; //Adding the compared number value and sring value to array.
}
arsort($sort_array, SORT_REGULAR);//Sorting the array by the larges number.
print_r ($sort_array);
//creating another foreach statement to get the output you wanted.
$count = 0;
foreach($sort_array as $key => $value){
$count++;
echo $count.". ".$key."\n";
};
?>
Results:
Array
(
[blend45] => 4
[book21] => 3
[airdrone] => 3
[march] => 2
[buzz] => 1
)
1. blend45
2. book21
3. airdrone
4. march
5. buzz
I think the levenshtein() function would be the most appropriate method to achieve your goal:
$array = array(
'mike'=>'book21',
'ben'=>'buzz',
'jack'=>'airdrone',
'july'=>'march',
'fred'=>'blend45'
);
$string = 'blenmaio2';
uasort($array, function($a, $b) use ($string) {
$aDistance = levenshtein($string, $a);
$bDistance = levenshtein($string, $b);
return ($aDistance < $bDistance) ? -1 : 1;
});
print_r($array);
// Output:
// Array
// (
// [fred] => blend45
// [july] => march
// [mike] => book21
// [ben] => buzz
// [jack] => airdrone
// )
http://php.net/levenshtein
Update Use uasort() instead of usort() to preserve the array keys.
I just noticed that my answer compares the similarity, but doesn't meet the highest character count match, so sorry for that :)
Here you are my answer. It is a bit different, because I'm using levenshtein function for finding nearest between two words.
I'm using uasort to reorder the array in way you liked.
Of course you can replace the algorithm for nearest by your function.
<?php
$array = array(
'mike'=>'book21',
'ben'=>'buzz',
'jack'=>'airdrone',
'july'=>'march',
'fred'=>'blend45'
);
$string = 'blenmaio2';
function cmp($a,$b){
global $string;
$aa=levenshtein($a, $string);
$bb=levenshtein($b, $string);
if($aa>$bb)
return 1;
elseif($bb>$aa)
return -1;
else return 0;
}
uasort($array,cmp);
?>
<pre><?= print_r($array); ?></pre>

How to append output of preg_match to an existing array?

I have two preg_match() calls and i want to merge the arrays instead of replacing the first array. my code so far:
$arr = Array();
$string1 = "Article: graphics card";
$string2 = "Price: 300 Euro";
$regex1 = "/Article[\:] (?P<article>.*)/";
$regex2 = "/Price[\:] (?P<price>[0-9]+) Euro/";
preg_match($regex1, $string1, $arr);
//output here:
$arr['article'] = "graphics card"
$arr['price'] = null
preg_match($regex2, $string2, $arr);
//output here:
$arr['article'] = null
$arr['price'] = "300"
How may I match so my output will be:
$arr['article'] = "graphics card"
$arr['price'] = "300"
?
You could use preg_replace_callback and handle the merging inside the callback function.
If it were me this is how I would do it, this would allow for easier extension at a later date, and would avoid using a callback function. It could also support searching one string easily by replacing $strs[$key] and the $strs array with a singular string var. It doesn't remove the numerical keys, but if you are only ever to go on accessing the associative keys from the array this will never cause a problem.
$strs = array();
$strs[] = "Article: graphics card";
$strs[] = "Price: 300 Euro";
$regs = array();
$regs[] = "/Article[\:] (?P<article>.*)/";
$regs[] = "/Price[\:] (?P<price>[0-9]+) Euro/";
$a = array();
foreach( $regs as $key => $reg ){
if ( preg_match($reg, $strs[$key], $b) ) {
$a += $b;
}
}
print_r($a);
/*
Array
(
[0] => Article: graphics card
[article] => graphics card
[1] => graphics card
[price] => 300
)
*/
You can use array_merge for this if you store your results in two different arrays.
But your output depicted above is not correct. You do not have $arr['price'] if you search with regex1 in your string but only $arr['article']. Same applies for the second preg_match.
That means if you store one result in $arr and one in $arr2 you can merge them into one array.
preg_match does not offer the functionality itself.
Use different array for second preg_match ,say $arr2
Traverse $arr2 as $key => $value .
Choose non null value out of $arr[$key] and $arr2[$key], and write that value to $arr[$key].
$arr will have required merged array.
This should work for your example:
array_merge( // selfexplanatory
array_filter( preg_match($regex1, $string1, $arr)?$arr:array() ), //removes null values
array_filter( preg_match($regex2, $string2, $arr)?$arr:array() )
);

Remove values with digit only from array - PHP

I have an array like so
array(
1=>hello,
2=>foo,
3=>192,
4=>keep characters AND digits like a1e2r5,
);
All I want to do is to remove rows containing digits ONLY (3=>192), and return an array like this one :
array(
1=>hello,
2=>foo,
3=>keep characters AND digits like a1e2r5,
);
I tried with array_filter but didn't get it work. Can someone show me how to do? Thanks
$data = array( 1 => "hello",
2 => "foo",
3 => "192",
4 => "keep characters AND digits like a1e2r5",
);
$result = array_filter( $data,
function($arrayEntry) {
return !is_numeric($arrayEntry);
}
);
Or using slightly more modern PHP, with arrow functions:
$result = array_filter( $data,
fn($arrayEntry) => !is_numeric($arrayEntry)
);
You could use a loop and the intval function.
$filteredArray = array();
foreach($array as $element){
//this works because PHP is weakly typed
if(intval($element) != $element){
$filteredArray[] = $element;
}
}
Are you sure you were using array_filter correctly? It's the best solution for your problem.
// named callback for backwards compatibility, but use an anonymous function
// if you have a high enough php version.
function callback($item) { return !is_numeric($item); }
$result = array_filter($a, 'callback');
print_r($result);
// optional - causes numeric keys to be in order
$result = array_values($result);
print_r($result);
Output using example input from question as $a:
Array
(
[1] => hello
[2] => foo
[4] => keep characters AND digits like a1e2r5
)
Array
(
[1] => hello
[2] => foo
[3] => keep characters AND digits like a1e2r5
)
I'm surprised no one mentioned this in any of the answers: using numeric tests is not a total solution. Using numeric tests will remove some elements containing non-digit characters if they are evaluated as numeric. Specifically, {e, -, .}
$data=array(
1=>'hello',
2=>'foo',
3=>'192',
4=>'keep characters AND digits like a1e2r5',
5=>'1.4',
6=>'-42',
7=>'1e2',
8=>'1.23e4',
);
function callback1($arrayEntry) {
return !is_numeric($arrayEntry);
}
$result = array_filter( $data, 'callback1');
echo '<pre>';
print_r($result);
echo '<hr>';
function callback2($arrayEntry) {
return !preg_match('/^[0-9]+$/', $arrayEntry);
}
$result = array_filter( $data, 'callback2');
print_r($result);

Want to got the new array that not in array A?

I have two arrays:
$A = array('a','b','c','d')
$c = array('b','c','e','f')
I want to get a new array containing items not in array $A. So it would be:
$result = array('e','f');
because 'e' and 'f' are not in $A.
Use array_diff
print_r(array_diff($c, $A)); returns
Array
(
[2] => e
[3] => f
)
Use array_diff for this task. As somewhat annoying it does not return all the differences between the two arrays. Only the elements from the first array passed which are not found in any other array passed as argument.
$array1 = array('a','b','c','d');
$array2 = array('b','c','e','f');
$result = array_diff($array2, $array1);
array_diff()
Pseduo Code for General Implementation
Disclaimer: Not familiar with PHP, other answers indicate there are a lot quicker ways of doing this :)
Loop through your first array:
// Array of results
array results[];
// Loop through all chars in first array
for i = 0; i < A.size; i++
{
// Have we found it in second array yet?
bool matched = false;
// Loop each character in 2nd array
for j = 0; j < C.size; j++
{
// If they match, exit the loop
if A[i] == C[J] then
matched = true;
exit for;
}
// If we have a match add it to results
if matches == true then results.add(A[i])
}

Categories