Assembling a variable from other variables based on a condition - php

Brain totally not working today.
So, I have a few columns in a table that basically designate whether a certain piece of information WAS or WAS NOT provided by the user.
For example, I have a table with:
| ID | USER | crit1 | crit2 | crit3 | crit4 | etc. |
Now, the record could have a 1 or yes for any of the "critX" fields. I dunno much about math and permutations, but I guess if there were 4 columns, you could have 16 combinations of output. In my real world example I have 16 different criteria, so I can't factor for the output of that mess. I need to write a routine of some sort.
In my example, each of those crit values is going to be evaluated and if the criterion == 1/yes, it will be included in another variable AND have a more human friendly bit of data assigned to it. I am currently pulling each value from the DB an doing something like
### first I pull the values
$mydbarray[crit1] = $cr1;
$mydbarray[crit2] = $cr2;
$mydbarray[crit3] = $cr3;
(etc...)
### then I assign some human friendly text ONLY if the value == 1/yes
if($cr1==1) ($cr1 = "This info is present!";}
if($cr2==1) ($cr2 = "Number two is present!";}
if($cr3==1) ($cr3 = "Three was provided!";}
Now, what I need to do, is collect all that output only if the "IF" fired on true and assemble into a final variable.
So somehow, I want:
$finaloutput = $cr1, $cr2, $cr3;
Obviously that's not valid or what I want, but even if it DID work, it would end up including all the == 0/no instances as well.
So essentially I need a conditional grouping of these variables and I am not getting it.
I was thinking of casting an array and looping through it, but then I was at a loss for including the human intelligible portions...
Some guy at work mentioned an IF statement using bool, but I am not wellversed there.
I would think this is easy, but I've been up all week with the baby. so my brain is broken.
Thanks in advance!!!
Rob

First of all much of what you wrote is not valid PHP. I will assume you wrote it just to illustrate the point and didn't bother with the syntax.
Here is how to do it:
You take an array in which you will put your texts:
$texts = array();
For each of your criteria you check if they are provided, but add to the array created before:
if($cr1==1) {$texts[] = "This info is present!";}
if($cr2==1) {$texts[] = "Number two is present!";}
if($cr3==1) {$texts[] = "Three was provided!";}
...
In the end you concatenate all your texts with implode:
$finaloutput = implode(', ', $texts);
I prefer the method with implode to the one that just appends to a string because if I want a comma separator I don't get an extra one at the end.
Good luck, Alin

Try this:
$finaloutput = '';
if($cr1) $finaloutput .= "This info is present! ";
if($cr2) $finaloutput .= "Number two is present! ";
if($cr3) $finaloutput .= "Three was provided! ";
echo $finaloutput;
You dont need brackets in an if statement if there is only one item inside it. Im not sure if you want commas in the variable though...

Related

Php: How to pull a value from an array in a single field in MySQL

In my database I have a table named posts. In it, the columns are:
Postid - 1
PostBody - my first post
Likers - 1,2,3,4,5,
Now what am trying to do is, in the likers field, am trying to pull the individual number without pulling all the data on the field. So if I want to retrieve likers No.3, I want the output to be 3 when I echo it out.
I have tried FIND_IN_SET(), and strstr(). All I get is the whole array, 1-5, being echoed. And because of that, I cannot match it with other variables(I.e. $var = 3;) which have the matching number.
Is there a way of doing this?
Thanx
If you really want to do it this way (read my comment first), what you can do is retrieve the comma-seperated data, explode it into a php array, and then use the array_search built-in function:
$likers_attribute_data = '1,2,3,4,5,';
$likers_array = explode(',', $likers_attribute_data);
// check if user 3 is a liker:
if (array_search('3', $likers_array) {
// he has :)
} else {
// he hasn't :(
}
Again, this is a very sloppy and inefficient way of doing business. Please just go with the solution in my comment!

Is there a simple way to return WHAT is similar between 2 strings in PHP?

I've looked into the similar_text() and levenshtein() functions, but they only seem to return THAT there are similarities and the percentage of those similarities.
What I am trying to do is compare 2 strings to determine WHAT is actually similar between the two.
Basically:
<?php
$string1 = "IMG_1";
$string2 = "IMG_2";
echo CompareTheseStrings($string1,$string2); // returns "IMG_";
If this wonderful function doesn't exist, what would be the best way to accomplish this?
My end game plan is to read through a list of file names and then replace the similar text with something user defined or just remove it all together, but I don't want to replace each files unique identifier.
Reading your 'end goal' I think you're going about this completely the wrong way I think you should really be looking at str_replace
$string1 = "IMG_1";
$string2 = "IMG_2";
// you would create a loop here to insert each string
str_replace("IMG", "NEW_TERM", $string1);
If you want to remove the text altogether then just pass an empty string in as the 2nd parameter

How to highlight search-matching text on a web page

I'm trying to write a PHP function that takes some text to be displayed on a web page, and then based on some entered search terms, highlights the corresponding parts of the text. Unfortunately, I'm having a couple of issues.
To better explain the two issues I'm having, let's imagine that the following innocuous string is being searched on and will be displayed on the web page:
My daughter was born on January 11, 2011.
My first problem is that if more than one search term is entered, any placeholder text I use to mark the start and end of any matches for the first term may then be matched by the second term.
For example, I'm currently using the following delimiting strings to mark the beginning and end of a match (upon which I use the preg_replace function at the end of the function to turn the delimiters into HTML span tags):
'#####highlightStart#####'
'#####highlightEnd#####'
The problem is, if I do a search like 2011 light, then 2011 will be matched first, giving me:
My daughter was born on January 11, #####highlightStart#####2011#####highlightEnd#####.
Upon which when light is searched for, it will match the word light within both #####highlightStart##### and #####highlightEnd#####, which I don't want.
One thought I had was to create some really obscure delimiting strings (in perhaps a foreign language) that would likely never be searched on, but I can't guarantee that any particular string will never be searched on and it just seems like a really kludgy solution. Basically, I imagine that there is a better way to do it.
Any advice on this first point would be greatly appreciated.
My second question has to do with how to handle overlapping matches.
For example, with the same string My daughter was born on January 11, 2011., if the entered search is Jan anuar, then Jan will be matched first, giving me:
My daughter was born on #####highlightStart#####Jan#####highlightEnd#####uary 11, 2011.
And because the delimiting text is now a part of the string, the second search term, anuar will never be matched.
Regarding this issue, I am quite perplexed and really have no clue how to solve it.
I feel like I need to somehow do all of the search operations on the original string separately and then somehow combine them at the end, but again, I'm lost on how to do this.
Perhaps there's a way better solution altogether, but I don't know what that would be.
Any advice or direction on how to solve either or both of these problems would be greatly appreciated.
Thank you.
In this case I think it's simpler to use str_replace (though it won't be perfect).
Assuming you've got an array of terms you want to highlight, I'll call it $aSearchTerms for the sake of argument... and that wrapping the highlighted terms in the HTML5 <mark> tag is acceptable (for the sake of legibility, you've stated it's going on a web-page and it's easy to strip_tags() from your search terms):
$aSearchTerms = ['Jan', 'anu', 'Feb', '11'];
$sinContent = "My daughter was born on January 11, 2011.";
foreach($aSearchTerms as $sinTerm) {
$sinContent = str_replace($sinTerm, "<mark>{$sinTerm}</mark>", $sinContent);
}
echo $sinContent;
// outputs: My d<mark>au</mark>ghter was born on <mark>Jan</mark>uary <mark>11</mark>, 20<mark>11</mark>.
It's not perfect since, using the data in that array, the first pass will change January to <mark>Jan</mark>uary which means anu will no longer match in January - something like this will, however, cover most usage needs.
EDIT
Oki - I'm not 100% certain this is sane but I took a totally different approach looking at the link #AlexAtNet posted:
https://stackoverflow.com/a/3631016/886824
What I've done is looked at the points in the string where the search term is found numerically (the indexes) and built an array of start and end indexes where the <mark> and </mark> tags are going to be entered.
Then using the answer above merged those start and end indexes together - this covers your overlapping matches issue.
Then I've looped that array and cut the original string up into substrings and glued it back together inserting the <mark> and </mark> tags at the relevant points (based on the indexes). This should cover your second issue so you're not having string replacements replacing string replacements.
The code in full looks like:
<?php
$sContent = "Captain's log, January 11, 2711 - Uranus";
$ainSearchTerms = array('Jan', 'asduih', 'anu', '11');
//lower-case it for substr_count
$sContentForSearching = strtolower($sContent);
//array of first and last positions of the terms within the string
$aTermPositions = array();
//loop through your search terms and build a multi-dimensional array
//of start and end indexes for each term
foreach($ainSearchTerms as $sinTerm) {
//lower-case the search term
$sinTermLower = strtolower($sinTerm);
$iTermPosition = 0;
$iTermLength = strlen($sinTermLower);
$iTermOccursCount = substr_count($sContentForSearching, $sinTermLower);
for($i=0; $i<$iTermOccursCount; $i++) {
//find the start and end positions for this term
$iStartIndex = strpos($sContentForSearching, $sinTermLower, $iTermPosition);
$iEndIndex = $iStartIndex + $iTermLength;
$aTermPositions[] = array($iStartIndex, $iEndIndex);
//update the term position
$iTermPosition = $iEndIndex + $i;
}
}
//taken directly from this answer https://stackoverflow.com/a/3631016/886824
//just replaced $data with $aTermPositions
//this sorts out the overlaps so that 'Jan' and 'anu' will merge into 'Janu'
//in January - whilst still matching 'anu' in Uranus
//
//This conveniently sorts all your start and end indexes in ascending order
usort($aTermPositions, function($a, $b)
{
return $a[0] - $b[0];
});
$n = 0; $len = count($aTermPositions);
for ($i = 1; $i < $len; ++$i)
{
if ($aTermPositions[$i][0] > $aTermPositions[$n][1] + 1)
$n = $i;
else
{
if ($aTermPositions[$n][1] < $aTermPositions[$i][1])
$aTermPositions[$n][1] = $aTermPositions[$i][1];
unset($aTermPositions[$i]);
}
}
$aTermPositions = array_values($aTermPositions);
//finally chop your original string into the bits
//where you want to insert <mark> and </mark>
if($aTermPositions) {
$iLastContentChunkIndex = 0;
$soutContent = "";
foreach($aTermPositions as $aChunkIndex) {
$soutContent .= substr($sContent, $iLastContentChunkIndex, $aChunkIndex[0] - $iLastContentChunkIndex)
. "<mark>" . substr($sContent, $aChunkIndex[0], $aChunkIndex[1] - $aChunkIndex[0]) . "</mark>";
$iLastContentChunkIndex = $aChunkIndex[1];
}
//... and the bit on the end
$soutContent .= substr($sContent, $iLastContentChunkIndex);
}
//this *should* output the following:
//Captain's log, <mark>Janu</mark>ary <mark>11</mark>, 27<mark>11</mark> - Ur<mark>anu</mark>s
echo $soutContent;
The inevitable gotcha!
Using this on content that's already HTML may fail horribly.
Given the string.
In January this year...
A search/mark of Jan will insert the <mark>/</mark> around 'Jan' which is fine. However a search mark of something like In Jan is going to fail as there's markup in the way :\
Can't think of a good way around that I'm afraid.
Do not modify original string and store the matches in the individual array, either starts in odd and ends in even elements or store them in records (arrays of two items).
After searching for the several keywords, you end up with several arrays with matches. So the task now is how to merge two lists of segments, producing the segments that covers the areas. As the lists are sorted, this is a trivial task that can be solved in O(n) time.
Then just insert highlight tokens into positions recorded in the resulting array.

Perform operations after extract()

I have been looking for an answer, but maybe because I am searching the wrong terms or concepts - I did not yet find any lead on how to perform operations on extracted arguments .
I have an array, which is dynamic ( I can not predict how many $vars or of what name or type )
global $o99_option;
extract( $o99_option );
so now, theoretically, I can have any number of $vars with any possible name..
example :
$first_var = 'first-var';
$my_second_var = 'another';
$enigma = NULL;
$answer = '42';
my question is - how can I perform operations on the result of extract ( after extraction ) in a manner that will effect all the created $vars ?
for example, let´s say I want to trim all of those variables - How do I achieve that ?
( that , In my twisted mind, should have the same effect as
foreach (extract( $o99_option ) as $single_var ){
do_something($single_var);
}
)
Edit I : So, is there a way to perform operations on all extracted elements ? ( assuming I DO need to extract them ..) Or should I always do that BEFORE the extraction ( for example with the help of array_map() ) - or, should I , like people here suggested just forget that extract ever existed never ever use it..
Edit II :
Sure, like many here said , I can also do
$first_var = $o99_option['first-var'];
$my_second_var = $o99_option['my_second_var'];
$enigma = $o99_option[enigma];
$answer = $o99_option['answer'];
but
1) it seems a little absurd doing that for 100+ variables, and
2 ) what to do with the ones that I need to use their value as name ?
right now, for example, I use
${$title_field} = $formdata[$post_title_field];
where I know that $title_field exists as $o99_option['title_field'], and therefore exists as a variable after extract ..
Again, I might be approaching that all wrong, but up until now the script works great , and actually , the first comment by #Mark Baker ( using array_map() ) might be the best option when doing so BEFORE the extract ...
You must not extract the variables, you need to keep them in the $o99_option array otherwise it's impossible to determine the number of elements.
foreach ($o99_option as $variable) {
// Do something with the variable
}
Imagine you're sitting in one of those kids ball pits. This is your variable scope. You have all sorts of variables floating around in this scope. Now you get handed a box full of even more colourful balls. Those balls are important balls, they're more interesting to you than all the other balls around you.
What you're doing with extract is you're turning the box upside down and empty all those balls into the ball pit and mix them with all the other balls. And you didn't even really know what balls were in that box exactly, but you emptied the box anyway. Well, good luck finding those balls again now and doing anything with them.
Keep the balls in the box! While they're in the box, you can inspect them one by one. You can look at each one in turn and do something with it. You can carry them all around inside that box together. Don't extract!
If you know what you're looking for in that box:
echo $o99_option['first-var'];
Simple. Just take that ball directly and do whatever you want with it.
If you want to check whether a specific ball is in the box:
if (isset($o99_option['first-var']))
If you want to look through all balls and do something with each of them:
foreach ($o99_option as $name => $ball) {
echo "$name: $ball";
}
If you want to do something to all the variables:
foreach ($o99_option as &$variable) {
$variable = strtoupper($variable); //for example
}
Then you should work with each element individually. Don't extract.

Matching an array of people for gift giving, how to handle this edge case

I'm matching an array of people to each other. They can't be matched with themselves and each person can only be matched with one other. I have worked this out but run into an edge case. If the person being matched is themselves the only person who has not yet been matched against, we are stuck.
Example:
$names = array('Dad','Mom','Harrald','Yu','Sandra','Dave', 'Andy & Kim');
$drawn = array();
$tn = count($names)-1;
$i = mt_rand(0, $tn);
foreach ($names as $name) {
while($name == $names[$i] || in_array($names[$i], $drawn)) {
$i = mt_rand(0, $tn);
}
echo $name. ' has ' . $names[$i].'<br />';
array_push($drawn, $names[$i]);
}
This could produce:
Dad has Sandra
Mom has Yu
Harrald has Dave
... etc, etc.
The problem is when it gets to the last element in the array, 'Andy & Kim', if 'Andy & Kim' are the only element not yet added to the $drawn array then we have an edge case because you can't match 'Andy & Kim' to themselves. In my example this can result in getting trapped in that while loop and eventually timing out... see what I mean? How would you handle this (this is solely for my own amusement as I went to knock out a quick gift giving match-up script for my Mom to use and realized this was a potential problem).
Oh, better ways to implement such a pattern would be most interesting to see. Thx!
Surely, rather than using iteration, it's easier just to shuffle the array; and then match 1st to 2nd, 2nd to 3rd, etc, with the last being matched to the 1st again to complete the circle
You need to backtrack at that point. There are many algorithms which require backtracking, because (as you've found) it turns out that a choice you made at an earlier stage was actually impossible.
You'll need to store the previous choice points in some way, so that when you hit impossibility (or succeed, if your task is to elicit all solutions) you can go back to the last not-fully-explored choice, and make a different choice.
Without matching someone that already has a match, you can't. That's how odd numbers work. :/
So either match with someone who already has a match, or ask your teacher not to give you bad inputs. ;)

Categories