php vs regex for counting data - php

i have an array, it have same data:
data range
115X0101-115X0200
115X0101-115X0200
115X0101-115X0200
the 115x mean production code..this unimportant.
we just concern at four digits behind it that we can counting.
1. i want script read or search "0101" and "0200" from 115X0101-115X0200
2. i have tried using regex to count them become 200-101=100
3. the "115X0101-115X0200" repeated until there are 20 data like this
4. after it reached 20, show result at page:
data range
100

If this is the raw data, the easiest way to extract it is probably using a regular expression, as you've mentioned.
You'll probably want something like this (in PHP):
# Get this from the database
$sql_results = array(
'115X0101-115X0200',
'115X0101-115X0200',
'115X0101-115X0200',
);
foreach($sql_results as $row)
{
preg_match_all('/\d{4}/', $row, $matches);
#200 #101
echo intval($matches[0][1]) - intval($matches[0][0]) + 1;
}
For each row, preg_match will find groups of 4 digits (\d{4}) and place them in $matches (use var_dump($matches) to see what it looks like).
More on Regex
Regular Expressions Cheatsheet
Regular Expressions Help
SQL Limit
Side note: If you only want 20 results at a time, you'll want to SELECT * FROM table LIMIT 20 when you query the database. To get rows 31-50 you'd use LIMIT 30, 20, which means offset by 30, then get 20 rows.

Related

How to make search in PHP

I have 3 distinct lists of strings. First one contains names of people(from 10 chars to 80 chars long). Second one - room numbers(903, 231 and so on). Last one - group numbers(ABCD-1312, CXVZ-123).
I have a query which is given by a user. Firstly, I tried to search using Levenshtein distance, it didn't work, because whenever user types 3 chars, it gives some room number, even though there is no any digit in query. Then, I tried similar_text(), it worked better, but because people names all have different length, it mostly gives results with shorter names.
Now, the best I come up with is using similar_text() and str_pad() to make each string equal length. Still doesn't work properly.
I want to somehow give extra weight to strings, if they have several matches in a row, or if query and my string starts with the same letter and so on.
$search_min_heap = new SearchMinHeap();
$query = strtolower($query); // similar_text is case sensitive, so make everything lowercase
foreach ($res["result"] as &$item) {
similar_text($query, str_pad(strtolower($item["name_en"]), 100, " "), $cur_distance_en);
similar_text($query, str_pad(strtolower($item["name_ru"]), 100, " "), $cur_distance_ru);
similar_text($query, str_pad(strtolower($item["name_kk"]), 100, " "), $cur_distance_kk);
$cur_max_distance = max($cur_distance_en, $cur_distance_ru, $cur_distance_kk);
$item["matching"] = $cur_max_distance;
$search_min_heap->insert($item);
}
$first_elements = $search_min_heap->getFirstElements($count);

ID number zero, one, o and i in query

We have a system that creates a 5 digit alpha-numeric string of numbers and letters. Originally, I had the full alphabet and 0-9 so something like the following was possible:
0O1I0
Because different fonts may be used on different systems, there was confusion between the o's and i's so I updated the function to only include the numbers. Because there are historical items with the "o" and "i" items I have been asked to modify our search to automatically look for a zero if an o is entered and a 1 if an i is entered (or vice versa).
These are 5 digit ids with 2 possible values for the specific character. I'm thinking I could loop over the value with PHP prior to writing the query to build a list of options and then check if "IN (list of items)" in my query. I don't know if there's something built in that I'm missing though in MySQL like..
WHERE ID = o/0, i/1, etc.
So how about parsing the id in php, replacing every occurence of 0 or O with regex string [o0], and similarly replacing i and 1 with [i1].
Then you could use this string in your query like this
WHERE id REGEXP '...[i1]...[o0]...'
The php code could look like this
$id = '0O1I0';
$id = preg_replace('/[i1]/i', '[i1]', $id);
$id = preg_replace('/[o0]/i', '[o0]', $id);
echo $id; // [i1][o0][i1][o0][o0]
...
mysqli_query($conn, "SELECT ... WHERE id REGEXP '$id'");
What about something like
select <stuff> from <table>
where replace(replace(upper(id), 'I', '1'), 'O', '0') like '%<number-search-term>%'
EDIT (more detail)
replace() in mysql takes three arguments: the original term, what to look for, and what to swap it with. In the where clause I did a nested replace. The inner one replaced any instances of I with 1 and the outer one took the inner replace as its argument (so with all Is as 1s) and replaced any Os with 0s. This is then compared against the number search term (I used a like statement).

Match SteamID with ban duration from listid result

I use a php library to execute commands on a srcds-server via rcon. In this case I want to get all bans and their durations. When I execute listid via rcon, I get, after some parsing, for example this text:
1 STEAM_1:0:12345678 : permanent 2 STEAM_1:0:87654321 : 30.000 min
Now I want to get an array which contains the SteamID and the duration per set, like this:
$Bans = [
"STEAM_1:0:12345678" => "permanent",
"STEAM_1:0:87654321" => "30.000 min",
]
Since I can't use explode in a good way to do this for me (or at least I don't know how I should do that), I want to try it with regex. My attempt so far:
/^(?:\d\s)(STEAM_[0-5]:[01]:[0-9]{1,8})(?:\s:\s)(permanent|\d{1,}\.000\smin)/g
But that doesn't match it in the right way. How would you do it?
The right regex with preg_match_all is:
preg_match_all("/(?:\d\s)(STEAM_[0-5]:[01]:[0-9]{1,8})(?:\s:\s)(permanent|\d{1,}\.000\smin)/", $input_lines, $output_array);
I needed to remove the ^. Now, I don't even have to do all the exploding beforehand. I matches the right parts even from the raw result:
ID filter list: 2 entries 1 STEAM_1:0:12345678 : permanent 2 STEAM_1:0:87654321 : 30.000 min L 05/20/2015 - 15:48:53: rcon from "188.40.142.20:60799": command "listid"

How to search partial/masked strings?

I am storing social security numbers in the database, but instead of storing whole numbers, I only store only 5 digits sequence. So, if SSN# is 123-12-1234, my database would store it #23121### or ####21234 or anything else, as long as it has a 5 digits in the row.
Therefore, when user enters whole SSN, I want the database to locate all matches.
So, I can do this :
SELECT * FROM user WHERE ssn like 123121234
But the query above would not work, since I have some masked characters in the SSN field (#23121###). Is there a good way of doing this?
Maybe a good way would be to use
SELECT * FROM user WHERE REPLACE (ssn, '#', '') like 123121234
Although there could be an issue - the query might return non-relevant matches since 5 numbers that I store in the DB could be anywhere in a sequence.
Any idea how to do a better search?
If the numbers are always in a sequential block, you can generate a very efficient query by just generating the 5 variations of the ssn that could be stored in the DB and search for all of them with an exact match. This query can also use indexes to speed things up.
SELECT *
FROM user
WHERE ssn IN ('12312####',
'#23121###',
'##31212##',
'###12123#',
'####21234');
I think you can do something like this:
Extract all possible 5-char combinations out of the queried SSN.
Make an IN() query on those numbers. I'm not sure though how many results you would get from this.
$n = 123121234;
$sequences = array();
for($i = 0; $i + 5 <= strlen($n); $i++) {
$sequences[] = substr($n, $i, 5);
}
var_dump($sequences);
Tell me if you need those hash sign surrounding the strings.

Creating a secuence of characters from a secuence of numbers in PHP

i have a database with many items in there, by the moment my users retrive info from the database using a simple php script who use GET parameters, like www.mypage.com/post.php?id=123432
Well at the beginning it was all fine, but know i have Ids that are very big (10000000). So at this point i dont my users to have that longs urls, so i think that changing the secuence of number for a secuence of leters will do the think, like post.php?id=XFBJ and then the php script knows that is the id=11223256437 for example. Any ideas of how to do this? Thanks!
I suppose you could do very simple trick to achieve that. Treat ID from URL as 36-based number and convert it to 10-based number before retrieving from database.
$_GET['id'] = '5yc1s';
$id = base_convert($_GET['id'], 36, 10); // 10000000
// SELECT ... FROM ... WHERE id = :id [id = $id]
And when you want to display a link do the opposite:
$id = 10000000;
$urlId = base_convert($id, 10, 36); // 5yc1s
// ...?id=$urlId
EDIT: Oh, base_convert() has upper limit of 36 (a-z0-9), not 32 - that makes your links even shorter. Of course you could write your own function that could convert up to 62-based numbers (a-zA-Z0-9) — that's a reasonable upper limit (of course even higher are available). Writing such a function is really easy.

Categories