need a simple programming logic solution.. - php

I am working on a CakePHP 2.x but right now my question has nothing to do with the syntax. I need a solution for this problem:
I have a table named messages in which there is a field name mobile numbers. The numbers are in this format:
12345678 and +9112345678 .. so they are both the same. The only difference is that in one number the country code is missing.
So I do this query in the database:
select the distinct numbers from messages tables..
Now it is taking these both numbers as distinct. But what I want is to take these both numbers as one.
How can I do this? In my DB there are several numbers with different country codes. Some have a country code and some don't, but I want to take both as one. The one in country code and the other without code. How can this be done?
At times now I have an array in which all the distinct numbers are stored. In this array there are numbers like this:
12345678 +9112345678
So now I don't know how to make a logic that I can take these numbers as one. If there is any solution for this then please share with some example code.

I don't think you can do this on the database level.
You would have to do something like this:
Create an array of all country codes (including + sign)
Fetch all the numbers from the database
Use array_map() and in the callback run strpos() against each
element in the country code array and if a match is made remove the
country code from the number
Finally after step 4 is finished run the number array through
array_unique()
CODE:
$country_codes = array('+91', '+61');
$numbers_from_db = array('33445322453', '+913232', '3232', '+614343', '024343');
$sanitized_numbers = array_map(function($number) use ($country_codes){
if(substr($number, 0, 1) === "0") {
$number = substr($number, 1);
return $number;
}
foreach($country_codes as $country_code) {
if(strpos($number, $country_code) !== false) {
$number = str_replace($country_code, "", $number);
return $number;
}
}
return $number;
}, $numbers_from_db);
$distinct_sanitized_numbers = array_unique($sanitized_numbers);
Tested and the out put of var_dump($distinct_sanitized_numbers) is:
array(4) {
[0]=>
string(11) "33445322453"
[1]=>
string(4) "3232"
[3]=>
string(4) "4343"
[4]=>
string(5) "24343"
}

Related

Is it possible to concatenate two values in an array together?

I’m new to PHP so this might be a very long questions. First of all I can’t normalise the database the way it has been designed it has to be kept like this. I’ll explain the scenario first: I have locations on a map, those locations can have as many products attached to them as possible. My issue is that I want to concatenate two values together in an array to make them into a string so I can store it in the db and then use it.
I’m having issues with a particular record, this record 1234 is causing me issues. As it has two Ratings attached to it but I need to concatenate them and put them into another array so I can store in my database in a particular field as strings instead of separate ints.
Below is the code, as you’ll see I did a if statement inside the code I want to use to debug what is happening in that particular record.
$ratingString = array();
$rating = 0;
foreach( //not sure if this foreach is related to the question)
if(true == isset($ratingString[$location[‘id’]])){
echo ‘in set’;
$ratingString[$location[‘id’]][‘ratingString’] = strval( $ratingString[$location[‘id’]][‘ratingString’]).’,’.$rating;
}else {
if($location[‘id’] == 1234){
echo ‘not in set’
$ratingString[$location[‘id’]][‘ratingString’] = $rating;
Print_r($ratingString);
} }
When I debug this, it shows me two variables in rating string.
Not in set
string() “ratingString”
array(1){
[1234] =>
array(1) {
[“ratingString”] =>
int(2)
}
}
Not in set
string() “ratingString”
array(1){
[1234] =>
array(1) {
[“ratingString”] =>
int(3)
}
}
So what I need help with, is how could I concatenate the two so that it would be [ratingString] => string 2,3 and how would I change my code so that it would work for all my locations and not just this particular record.

How to correctly parse .ini file with PHP

I am parsing .ini file which looks like this (structure is same just much longer)
It is always 3 lines for one vehicle. Each lines have left site and right site. While left site is always same right site is changing.
00code42=52
00name42=Q7 03/06-05/12 (4L) [V] [S] [3D] [IRE] [52]
00type42=Car
00code43=5F
00name43=Q7 od 06/12 (4L) [V] [S] [3D] [5F]
00type43=Car
What I am doing with it is:
$ini = parse_ini_file('files/models.ini', false, INI_SCANNER_RAW);
foreach($ini as $code => $name)
{
//some code here
}
Each value for each car is somehow important for me and I can get to each it but really specifily and I need your help to find correct logic.
What I need to get:
mCode (from first car it is 00)
code (from first car it is 52)
vehicle (from first car it is Q7 03/06-05/12 (4L))
values from [] (for first car it is V, S, 3D, IRE , 52
vehicle type ( for first car it is "car")
How I get code from right site:
$mcode = substr($code, 0, 2); //$code comes from foreach
echo "MCode:".$mcode;
How I get vehicle type:
echo $name; // $name from foreach
How I parse values like vehicle and values from brackets:
$arr = preg_split('/\h*[][]/', $name, -1, PREG_SPLIT_NO_EMPTY); // $name comes from foreach
array(6) { [0]=> string(19) "Q7 03/06-05/12 (4L)" [1]=> string(1) "V" [2]=> string(1) "S" [3]=> string(2) "3D" [4]=> string(3) "IRE" [5]=> string(2) "52" }
So basicly I can get to each value I need just not sure how to write logic for work with it.
In general I can skip the first line of each car because all values from there is in another lines as well
I need just 2th and 3th line but how can I skip lines like this? (was thinking to do something like :
if($number % 3 == 0) but I dont know how number of lines.
After I get all data I cant just echo it somewhere but I also need to store it in DB so how can I do this if
I will really appriciate your help to find me correct way how to get this data in right cycle and then call function to insert them all to DB.
EDIT:
I was thinking about something like:
http://pastebin.com/C97cx6s0
But this is just structure which not working
If your data is consistent, use array_chunk, array_keys, and array_values
foreach(array_chunk($ini, 3, true) as $data)
{
// $data is an array of just the 3 that are related
$mcode = substr(array_keys($data)[0], 0, 2);
$nameLine = array_values($data)[1];
$typeLine = array_values($data)[2];
//.. parse the name and type lines here.
//.. add to DB
}

in_array not finding an element

I am using a PDO approach to get an array out of database:
$statement = $db->prepare("SELECT sname FROM list WHERE ongoing = 1;");
$statement->execute();
$snames = $statement->fetchAll(PDO::FETCH_COLUMN, 0);
var_dump($snames);
The dump output is (total 2500 results):
[69]=> string(13) "ah-my-goddess"
[70]=> string(17) "ahiru-no-oujisama"
[71]=> string(13) "ahiru-no-sora"
Then I check if array $snames contains the new element $sname:
$sname = current(explode(".", $href_word_array[count($href_word_array)-1]));
if (in_array($sname, $snames) == False)
{
echo "New '$sname'!<br>";
}
else
{
echo "$sname is already in the list. Excluding.<br>";
unset($snames[$sname]);
}
And the output is:
'ah-my-goddess' is already in the list. Excluding.
New 'ahiru-no-oujisama'!
'ahiru-no-sora' is already in the list. Excluding.
Why does it says that 'ahiru-no-oujisama' is the new name? We can see from the DUMP function that the array contains this element.
I have compared the results a thousand times. Notepad finds both names. There are no spaces. Name in the database is the same as in variable..
For the record - I have around 2500 entities in $snames array and for 95% of records (+-) I am getting the "already exists" result. However, for some I am getting "new".
Is that perhaps some kind of encoding issue? For the table I have DEFAULT CHARSET=latin1. Could that be a problem?
Edit
It was suggested that I added a trim operation:
$snames = $statement->fetchAll(PDO::FETCH_COLUMN, 0);
for ($i=0; $i < Count($snames); $i+=1)
{
$snames[$i] = trim($snames[$i]);
}
and:
if (in_array(trim($sname), $snames) == False)
However I get the same problem.
Apparently, the problem was with line:
unset($snames[$sname]);
for some entries I had names such as "70" and "111"
as the result command:
unset($snames[$sname]);
removed elements at that position. Not the elements with such keys!! I.e. That's how program understood it:
unset($snames[77]);
and that's what I was expecting:
unset($snames['77']);
so the line had to be changed to following:
if(($key = array_search($sname, $snames)) !== false)
{
unset($snames[$key]);
}

Improving algorithm using MySQL

The code below is written mainly using PHP, but I am hoping to speed up the process, and parsing strings in PHP is slow.
Assume the following where I get a string from the database, and converted it into an array.
$data['options_list'] = array(
"Colours" => array('red','blue','green','purple'),
"Length" => array('3','4','5','6'),
"Voltage" => array('6v','12v','15v'),
);
These subarrays will each be a dropdown Select list, an the end user can select exactly 1 from each of the select lists.
When the user hits submit, I will want to match the submitted values against a "price table" pre-defined by the admins. Potentially "red" and "6v" would cost $5, but "red" and "5"(length) and "6v" would cost $6.
The question is, how to do so?
Currently the approach I have taken is such:
Upon submission of the form (of the 3 select lists), I get the relevant price rules set by the admin from the database. I've made an example of results.
$data['price_table'] =
array(
'red;4'=>'2',
'red;5'=>'3',
'red;6'=>'4',
'blue;3'=>'5',
'blue;4'=>'6',
'blue;5'=>'7',
'blue;6'=>'8',
'green;3'=>'9',
'green;4'=>'10',
'green;5'=>'11',
'green;6'=>'12',
'purple;3'=>'13',
'purple;4'=>'14',
'purple;5'=>'15',
'purple;6'=>'16',
'red;3'=>'1',
'red;3;12v'=>'17',
'blue;6;15v'=>'18',
);
Note : The order of the above example can be of any order, and the algorithm should work.
I then explode each of the above elements into an array, and gets the result that matches the best score.
$option_choices = $this->input->post('select');
$score = 0;
foreach($data['price_table'] as $key=>$value)
{
$temp = 0;
$keys = explode(';',$key);
foreach($keys as $k)
{
if(in_array($k, $option_choices))
{
$temp++;
}else{
$temp--;
}
}
if($temp > $score)
{
$score = $temp;
$result = $value;
}
}
echo "Result : ".$result;
Examples of expected results:
Selected options: "red","5"
Result: 3
Selected Options: "3", "red"
Result: 1
Selected Options: "red", "3", "12v"
Result: 17
The current method works as expected. However, handling these using PHP is slow. I've thought of using JSON, but that would mean that I would be giving the users my whole price table, which isn't really what I am looking for. I have also thought of using another language, (e.g python) but it wouldn't particularly be practical considering the costs. That leaves me with MySQL.
If someone can suggest a cheap and cost-efficient way to do this, please provide and example. Better still if you could provide an even better PHP solution to this which works fast.
Thank you!
It looks like you did work to make the results read faster but you're still parsing and testing every array part against the full list? This would probably run faster moving the search to MySQL and having extra columns there.
Since you can control the array (or test string) perhaps try fixed length strings:
$results = explode("\n", "
1 Red v1
22 Blue v2
333 Green v3");
$i = 0;
while($i < count($results)) {
$a = substr($results[$i], 0, 10);
$b = substr($results[$i], 10, 20);
$c = substr($results[$i], strpos(' ', strrev($results[$i]))-1);
if(stripos($userInput, $a . $b . $c) !== false) {
// parse more...
Supposedly JavaScript is good at this with memoizaion:
http://addyosmani.com/blog/faster-javascript-memoization/

How to efficiently combine two (or more) associative arrays with common keys

More generally, let's say we have two lists of different lengths with one common attribute:
list1: {
{"orderID":1234, "FirstName":"shaheeb", "LastName":"roshan"},
{"orderID":9183, "FirstName":"robert", "LastName":"gibbons"},
{"orderID":2321, "FirstName":"chester"},
}
list2: {
{"orderID":1234, "cell":"555-555-5555", "email":"roshan#fake.com"},
{"orderID":2321, "email":"chester#fake.com"},
}
I would like these combined into:
list3: {
{"orderID":1234, "FirstName":"shaheeb", "LastName":"roshan", "cell":"555-555-5555", "email":"roshan#fake.com"},
{"orderID":9183, "FirstName":"robert", "LastName":"gibbons"},
{"orderID":2321, "FirstName":"chester", "email":"chester#fake.com"},
}
I'm primarily a PHP developer, and I came up with the following:
function mergeArrays($a1, $a2) {
$larger = (count($a1) > count($a2)) ? $a1 : $a2;
$smaller = ($larger == $a1) ? $a2 : $a1;
$combinedArray = array();
foreach ($larger AS $key=>$largerSet) {
$combinedRow = array();
if (isset ($smaller[$key]) ) {
$combinedRow = $largerSet + $smaller[$key];
$combinedArray[$key] = $combinedRow;
}else {
$combinedArray[$key] = $largerSet;
}
}
return ($combinedArray);
}
If tested with the following:
$array1 = array("12345"=>array("OrderID"=>12345, "Apt"=>"blue"));
$array2 = array(
"12345"=>array("OrderID"=>12345, "AnotherCol"=>"Goons", "furtherColumns"=>"More Data"),
"13433"=>array("OrderID"=>32544, "Yellow"=>"Submarine")
);
The mergeArrays($array1, $array2) outputs the following:
array(2) {
[12345]=>
array(4) {
["OrderID"]=>
int(12345)
["AnotherCol"]=>
string(5) "Goons"
["furtherColumns"]=>
string(9) "More Data"
["Apt"]=>
string(4) "blue"
}
[13433]=>
array(2) {
["OrderID"]=>
int(32544)
["Yellow"]=>
string(9) "Submarine"
}
}
But I just don't feel like this is the most elegant solution. For example, I should be able to combine n number of arrays. Not really sure how I would accomplish that. Also, just looking at that bit of code, I'm fairly certain there are far more effective ways to accomplish this requirement.
As a learning point, I am curious whether python experts would take this opportunity to show up us PHP folk :). For that matter, I am curious whether Excel/VBA can even handle this. That is where I started trying to solve this problem with the thought that "surely excel can handle lists!".
I am fully aware that there are many many variations of this question around SO. I have looked at several of these, and still felt that I should try my version out here.
Your thoughts are most appreciated.
Thank you!
SR
For a general solution in Python, for any number of lists:
orders = defaultdict(dict)
for order_list in order_lists:
for order in order_list:
orders[order['orderID']].update(order)
See it working online: ideone
A generic solution that can merge any number of dicts (or a list of dicts - if you have more than one list, just add them together before calling the function):
from collections import defaultdict
def merge_dicts_by_key(key, *dicts):
return reduce(lambda acc,val: acc[val[key]].update(val) or acc,
dicts,
defaultdict(dict))
Call like so:
merge_dicts_by_key('orderId', dict1, dict2, dict3)
or, if you have lists of dicts:
merge_dicts_by_key('orderId', *list_of_dicts)
merge_dicts_by_key('orderId', *(list1 + list2))
Well, you could always replace your function with array_merge_recursive.

Categories