I have a challenge that I have not been able to figure out, but it seems like it could be fun and relatively easy for someone who thinks in algorithms...
If my search term has a "?" character in it, it means that it should not care if the preceding character is there (as in regex). But I want my program to print out all the possible results.
A few examples: "tab?le" should print out "table" and "tale". The number of results is always 2 to the power of the number of question marks. As another example: "carn?ati?on" should print out:
caraton
caration
carnaton
carnation
I'm looking for a function that will take in the word with the question marks and output an array with all the results...
Following your example of "carn?ati?on":
You can split the word/string into an array on "?" then the last character of each string in the array will be the optional character:
[0] => carn
[1] => ati
[2] => on
You can then create the two separate possibilities (ie. with and without that last character) for each element in the first array and map these permutations to another array. Note the last element should be ignored for the above transformation since it doesn't apply. I would make it of the form:
[0] => [carn, car]
[1] => [ati, at]
[2] => [on]
Then I would iterate over each element in the sub arrays to compute all the different combinations.
If you get stuck in applying this process just post a comment.
I think a loop like this should work:
$to_process = array("carn?ati?on");
$results = array();
while($item = array_shift($to_process)) {
$pos = strpos($item,"?");
if( $pos === false) {
$results[] = $item;
}
elseif( $pos === 0) {
throw new Exception("A term (".$item.") cannot begin with ?");
}
else {
$to_process[] = substr($item,0,$pos).substr($item,$pos+1);
$to_process[] = substr($item,0,$pos-1).substr($item,$pos+1);
}
}
var_dump($results);
Related
I am a newbie here and I have a php array of some strings, such as {"VAL1","VAL2", "VAL3", "VAL4"} and I have a larger string (normally a text file). The text file contains the elements of the arrays at different positions and some or all may be repeating more than one. Each of of the elements of the array that are contained in the text file are immediately followed by a time of occurence, for example, "VAL1 0900UTC and other text information".The problem now is that I want to find the occurrence(s) of all of the elements of the array in the text file and the time value following the element.
Please note that some of the elements may occur more than once at different positions with different time value in the textfile.
Already, I can load the textfile and get all of the elements.:
$mytextfile = preg_replace('/\s+/', ' ', strtoupper(file_get_contents($textpath."/". $textfile)));
$substr = array("REALTK","BGPTK", "SUDTK", "BECTK");
$bigstring = "REALTK 1000UTC 16/14 1011 BGPTK 1030UTC 10/12 992 REALTK 1145UTC 00/14 2222 SUDTK 1412UTC 11/06 1011 REALTK 1600UTC 16/14 1015 ...";
//I created variables to hold all element occuring to false
$is_val1 = false; $is_val2 = false;$is_val3 = false; $is_val4 = false;
//I created variables to count how many of each substring exist in the string
$numofval1=$numofval2=$numofval3=$numofval4=0;
if(strpos($bigstring, $substr[0]) !== false) {
$is_val1 = true;
//if exist, count how many times
$numofval1 = substr_count(strtoupper($bigstring),$substr[0]);
} e.t.c
I have been able to get the occurrence of each of the array elements in the big string
I have been able to detect if any of the array elements occur more than once in big string and number of times it does.
But I have not being able to get them in the sequence they occur with their position in the textfile string and the time value after each element.
$mytextfile = preg_replace('/\s+/', ' ', strtoupper(file_get_contents($textpath."/". $textfile)));
$substr = array("REALTK","BGPTK", "SUDTK", "BECTK");
//this is a sample content of the textfile
$bigstring = "REALTK 1000UTC 16/14 1011 BGPTK 1030UTC 10/12 992 REALTK 1145UTC 00/14 2222 SUDTK 1412UTC 11/06 1011 REALTK 1600UTC 16/14 1015 ...";
//I created variables to hold all element occuring to false
$is_realtk = false; $is_bgptk = false;$is_sudtk = false; $is_bectk = false;
//I created variables to count how many of each of the element exist in the text file string
$numofrealtk=$numofbgptk=$numofsudtk=$numofbectk=0;
if(strpos($bigstring, $substr[0]) !== false) {
$is_realtk = true;
//if exist, count how many times
$numofrealtk = substr_count(strtoupper($bigstring),$substr[0]);
} e.t.c
What I need is to get the Elements of the array in the order in which they occur in the text file with their position and time value
REALTK POSITION1 1000UTC
BGPTK POSITION5 1030UTC
REALTK POSITION8 1145UTC
SUDTK POSITION13 1412UTC
REALTK POSITION17 1600UTC
I also want to store the element => timevalue as associative array.
Thanks in anticipation.
Here is the snippet for you, please see inline doc for explanation
$substr = array("VAL1","VAL2", "VAL3", "VAL4");
$bigstring = "OTHERS VAL1 VAL4 VAL1 OTHERS OTHERS VAL2 OTHERS";
// considering space to explode words and having numbers in it
$temp = array_unique(str_word_count($bigstring, 1,"0..9"));
// sorting generated array and keeping index of value
asort($temp);
// matching records from array
$temp = array_intersect($temp,$substr);
// showing all the data you want
array_walk($temp,function($item,$k){
echo $item.' POSITION '.$k."\n"; // replace \n with <br/> if web
});
Working demo.
If the elements in your $bigstring are always divided by a whitespace, you can explode:
$val_arr = array( "REALTK" => array(), "BGPTK" => array(), "SUDTK" => array(), "BECTK" => array();
$bigstring_arr = explode( " ", $bigstring);
foreach( $bigstring_arr as $key => $part ){
if( in_array( $part, $substr ) ){
$val_arr[$part][] = array( "position" => $key+1, "time" => $bigstring_arr[$key+1] );
}
}
If it's not you can also explode directly on each element of Val1, Val2... . The code gets a bit more complicated then. But it would work as well if you created a new array in the form of "CountOfAllCharsInBigstringBeforeOccurence" => "KeyOfValInSubstr". From that you can derive your ordering with the vals.
Edit:
I edited the code based on your comment. Please note that it is not possible to have an array that has the same key multiple times which is why the solution here will have multiple dimensions.
I have an array which returns something like this:
[44] => 165,text:Where is this city:,photo:c157,correct:0,answers:[{text:Pery.,correct:true},{text:Cuba.,correct:false},{text:Brazil.,correct:false}]},{
I would like to get all the numbers from the beginning of the string until the first occurrence of a comma in the array element value. In this case that would be number 165 and I want to place that number in another array named $newQuesitons as key questionID
Next part will be to get the string after the first occurrence of : until the next occurrence of : and add it into the same array ($newQuestions) as key question.
Next part will be the photo:, that is I need to get the string after the photo: until the next occurrence of the comma, in this case peace of the string extracted will be c157.
I would like to add that as new key named photo in the array $newQuestions
I think this may be able to help you
<?php
$input = '165,text:Where is this city:,photo:c157,correct:0';
//define our new array
$newQuestions = Array();
//first part states we need to get all the numbers from the beginning of the string until the first occurence of a ',' as this is our array key
//$arrayKey[0] is our arrayKey
$arrayKey = explode(',',$input);
//second part requires us to loop through the array and split up the strings by comma and colon
foreach($arrayKey as $data){
//split each text into 2 by the colon
$item = explode(':',$data);
//we are only interested in items that have a colon in them, if we split it and the input has no colon, the count would be 0, so this check is used to ignore those
if(count($item) > 0) {
//now we can build our array
$newQuestions[$arrayKey[0]][$item[0]] = $item[1];
}
}
//output array
print_r($newQuestions);
?>
I don't fully understand the inputted array so the code above will most likely have to be tweaked, but atleast it gives you some logic to go from.
The output of this was: Array ( [165] => Array ( [165] => [text] => Where is this city [photo] => c157 [correct] => 0 ) )
I get my own solution, at least for the part of the problem. I manage to get the questionID using the following code:
$newQuestions = array();
foreach ($arrQuestions as $key => $question) {
$substring = substr($question, 0, strpos($question, ','));
$newQuestions[]['questionID'] = $substring;
}
I am now trying to do the same thing for the question part. I will update this code in case that someone else may have similar task to accomplish.
I need to get the value for a certain key, they key is not the same all the time.
initial part remains same but every time I get new id added in the end.
My array is like this:
senario 1:
Array
(
[custom_194_1] => 123
[_f_upload] => Save
)
senario 2:
Array
(
[custom_194_2] => 456
[_f_upload] => Save
)
I need to get the value 123 in senario 1, 456 in senario 2.
Can anyone please help me on how to get the value from this array key.
If your key is always the first element, and the array is $array the fastest way is:
$result = reset($array);
Or if you don't want to mess with the array's internal pointer:
$result = array_values($array)[0];
If you want the value of the key:
$key = array_keys($array)[0];
Thanks for your time guys. I'm using foreach to loop through and then checking with every key with substring. Hope it helps someone in future, not the very best solution though.
foreach($fields as $key => $val)
{
if(substr($key,0,10)=='custom_194'){
$realValue = $val;
echo "<br>value i'm looking for:";print_r($val);
}
}
Because you stated that you want the number at the end of the key and because you appear to want to learn more about regular expressions... This is not a hard task to do with preg_match.
Assume $array is the array that you begin with that has all the key=>val values.
foreach($fields as $key=>$val)
{
if(preg_match('/^custom_194_([0-9]+)$/', $key, $matches))
{
$num = $matches[1];
print "Key number $num has value $val\n";
}
}
The regular expression is ^custom_194_([0-9]+)$. The ^ means "beginning of the string." The $ means "end of the string." You can see that we explicitly spell out custom_194_. Then, we use ( and ) to identify a substring that we want to keep in the matches array. Inside ( and ), we look for the characters 0 through 9 using [0-9]. The + means "1 or more characters." So, we want 1 or more 0 through 9 characters.
The match array contains the entire string matched in the first index and then each sub-match in the remaining indexes. We only have one sub-match, which will be in index 1. So, $num is in $matches[1].
was wondering if there's a function to search an array, where the first letter matches a letter chosen. I could do something less elegant like
Loop through array
Each item remove the first character, match to chosen search variable e.g if the first letter from apple, a equals my selection a, show.
Your question is not clear. But below I give you an example of selecting only the selected elements of an array that contain the first letter you want:
function select_from_array($first_letter,$array){
$return = Array();
for($i=0;$i<count($array);$i++){
if($array[$i][0] === $first_letter) $return[] = $array[$i];
}
return $return;
}
Example:
$arr = Array("Nice","Chops","Plot","Club");
print_r(select_from_array('C',$arr));
Result:
Array
(
[0] => Chops
[1] => Club
)
I've been given a datafile where the original creator used alphabetical rather than numeric values to show order.
For example, if there's ten items, they'd be named:
12342313A
12342313B
12342313C
12342313D
12342313E
...
I need to import these values into a mySQL table that has order as a required int column, and I need to convert the letter to a number.
Is there a function in PHP to get a numeric value for a letter? Or will I need to do a substr to grab the trailing letter, and create an indexed array of letters and just do a lookup against that array?
I'm hesitant to do the simple way above, since I don't know how many objects could potentially exist, and I could need to write an array from A-AAAA or something.
Try converting it from base 36 to base 10 using base_convert(), I.e. base_convert($str, 36, 10). You might need to strtolower it first, and it'll only work if its not case sensitive.
PHP has a simple way to create that array, so you could write a function to figure all that out for you and do something like:
function str_to_num($letters, $max = 'ZZZZZZ') {
$count = 0;
for ($i = 'A'; $i < $max; $i++) {
$count++;
if ($letters == $i)
return $count;
}
}
Then you could do the substr, find the letters at the end, and then pass it into the function:
str_to_num('A'); // returns 1
str_to_num('AB'); // returns 28
str_to_num('AC'); // returns 29
str_to_num('ABC'); // returns 731
Something like that, anyway.
Good luck.
Assuming this is a one-time problem that you've got to correct and won't encounter moving forward, I suggest you use sort to... erm, sort out the problem. Let's say you have all those alpha-numeric order fields in an array, like so:
$vals = array (
'12342313A',
'12342313D',
'12342313E',
'12342313B',
'12342313C'
);
Those are all mixed up, not in order. But, you can call the function sort (docs) on that array and PHP does a decent job of making sense out of it:
print '<pre>Unsorted: ';
print_r($vals);
print '</pre>';
sort($vals);
print '<pre>Sorted: ';
print_r($vals);
print '</pre>';
/*
Unsorted: Array
(
[0] => 12342313A
[1] => 12342313D
[2] => 12342313E
[3] => 12342313B
[4] => 12342313C
)
Sorted: Array
(
[0] => 12342313A
[1] => 12342313B
[2] => 12342313C
[3] => 12342313D
[4] => 12342313E
)
*/
So far, so good. Now, you've got them ordered, and as a bonus you can use the index of the array as your new field in the database. Alter the table and add a field to hold the new value; we'll call this field numeric_order, and in my sample I've called the field that currently holds the alpha-numeric sort data string_order. Loop your sorted array and update the database (for example):
foreach ($vals as $x=>$v) {
$sql = 'UPDATE myTable SET numeric_order = '.($x+1).' WHERE string_order = "'.$v.'"';
}
I add 1 to x in the loop based on the assumption that you don't want anything to have 0 for the order - if that isn't a concern, then you can just use x. This is also predicated on the assumption that no two rows have the same alpha-numeric sort value.
If they do, then all is not lost! Start with your array looking like this:
$vals = array (
3=>'12342313A',
15=>'12342313D',
66=>'12342313E',
101=>'12342313B',
200=>'12342313C'
);
... the numeric keys would represent the unique/primary key of the corresponding row. Instead of sort, which does not preserve keys, use asort (which does preserve keys - docs), and then your loop looks like this:
$ord = 1
foreach ($vals as $x=>$v) {
$sql = 'UPDATE myTable SET numeric_order = '.$ord.' WHERE id = "'.$x.'"';
$ord++;
}
If my base assumption is wrong, and you'll continue to deal with this method of ordering rows, then in my humble view you ought to re-consider your data design.
use ord() with substr and subtract 64. This will set A to 1, B to 2, etc...
From what you have above, it seems like your values (last digit, at least) can be thought as being hex numbers. You can then transform them into decimal numbers through the hexdec function.
http://php.net/manual/en/function.hexdec.php