Random array, showing less than 3 of the same - php

I am using a random PHP array for a raffle type script and I sometimes get the same string 3 or more times. How can I limit the random to only show a max of 2 of the same string?
For example I have:
<?php
$raffle = array('string1', 'string2', 'string3', 'string4', 'string5', 'string6');
echo $raffle[array_rand($raffle)] . ", " . $raffle[array_rand($raffle)] . ", " . $raffle[array_rand($raffle)] . ", " . $raffle[array_rand($raffle)];
?>
So it chooses a random of 4 strings from the array, but I don't want the same string to show up more than twice. How can I achieve this?

Below is a function that will store what has been pick, and if picked again, remove it from the array. Once removed from the array, it'll never get picked again. So items can show up twice, but not more:
function pull_raffle() {
static $raffle = array('string1', 'string2', 'string3', 'string4', 'string5', 'string6');
static $pulled_before = array();
$pick = array_rand($raffle);
$string = $raffle[$pick];
if (array_key_exists($string, $pulled_before)) {
unset($raffle[$pick]);
} else {
$pulled_before[$string] = true;
}
return $string;
}
Use it like this:
echo pull_raffle() . ", " . pull_raffle(). ", " . pull_raffle() . ", " . pull_raffle();

Related

Adding looped data into associative array with readline

Writing a small program to ask some people their dreams for fun. I'm trying to put the data into an associative array. I want it to come out like this (for example three names:
How many people should I ask their dreams?
*number*
What is your name?
*name*
What is your dream?
*dream*
name's dream is: dream
My code is as follows:
<?php
echo "How many people should I ask their dreams?" . PHP_EOL;
$many = readline();
$dreams = [];
if (is_numeric($many)) {
for ($i = 1; $i <= $many; $i++) {
echo "What is your name?" . PHP_EOL;
$dreams[] = readline() . PHP_EOL;
echo "What is your dream?" . PHP_EOL;
$dreams[] = readline() . PHP_EOL;
}
echo "In jouw bucketlist staat: " . PHP_EOL;
foreach ($dreams as $key => $value) {
echo $key . "'s dream is: " . $value;
}
} else {
exit($hoeveel . ' is geen getal, probeer het opnieuw');
}
?>
It keeps returning this:
0's dream is: *name*
1's dream is: *name*
etcetera.
When you read values from the $dreams array with foreach ($dreams as $key => $value), you're expecting names as keys, but that's not how you inserted the values. You can use the name as the array key like this instead:
for ($i = 1; $i <= $many; $i++) {
echo "What is your name?" . PHP_EOL;
// set a name variable here
$name = readline() . PHP_EOL;
echo "What is your dream?" . PHP_EOL;
// then use that variable as the array key here
$dreams[$name] = readline() . PHP_EOL;
}

Loop through associative array and assign values

I have an array:
$instructions = array (
array("step_no"=>"1","description"=>"Ensure that you have sufficient balance"),
array("step_no"=>"2","description"=>"Approve the request sent to your phone")
);
What I want is to loop through this array, which I have done, but I am now confused because I don't know how to get the output I desire.
foreach ($array as $key => $value) {
//echo $key . "\n";
foreach ($value as $sub_key => $sub_val) {
if (is_array($sub_val)) {
//echo $sub_key . " : \n";
foreach ($sub_val as $k => $v) {
echo "\t" .$k . " = " . $v . "\n";
}
} else {
echo $sub_key . " = " . $sub_val . "\n";
}
}
}
The above code loops through the array, but this line of code:
echo $sub_key . " = " . $sub_val . "\n";
gives me:
step_no = 1 description = Ensure that you have sufficient balance step_no = 2 description = Approve the request sent to your phone
when I change it to:
echo $sub_val . "\n";
it gives me:
1 Ensure that you have sufficient balance 2 Approve the request sent to your phone
But I what I truly want is:
1. Ensure that you have sufficient balance
2. Approve the request sent to your phone
Is this possible at all? Thanks.
$instructions = array (
array("step_no"=>"1","description"=>"Ensure that you have sufficient balance"),
array("step_no"=>"2","description"=>"Approve the request sent to your phone")
);
foreach($instructions as $instruction) {
echo $instruction['step_no'] . '. ' . $instruction['description'] . "\n";
}
If it's HTML you may want to use <ol> and <li>.
It smells like you are not running this script in command line but in browser. If so, then \n makes no visual effect (unless within <pre> block) and you u must use HTML tag <br /> instead. Also, drop concatenation madness and use variable substitution:
echo "{$sub_key}. = {$sub_val}<br/>";
You can simple achieve this way
<?php
$instructions = array (
array("step_no"=>"1","description"=>"Ensure that you have sufficient balance"),
array("step_no"=>"2","description"=>"Approve the request sent to your phone")
);
foreach($instructions as $instruction){
echo $instruction['step_no'].'. '.$instruction['description'].PHP_EOL;
}
?>
Alway keep it simple.

Getting Max Value from an array

Hi I am trying to use an api from postcodeanywhere that calcuates the total travel time and distance for a particular journey, and I have got it working using the following code:
//Build URL Request
$url = "http://services.postcodeanywhere.co.uk/DistancesAndDirections/Interactive/Directions/v2.00/xmla.ws?";
$url .= "&Key=" . urlencode($Key);
$url .= "&Start=" . urlencode($Start);
$url .= "&Finish=" . urlencode($Finish);
$url .= "&DistanceType=" . urlencode($DistanceType);
//Make the request to Postcode Anywhere and parse the XML returned
$file = simplexml_load_file($url);
//Check for an error, if there is one then throw an exception
if ($file->Columns->Column->attributes()->Name == "Error")
{
throw new Exception("[ID] " . $file->Rows->Row->attributes()->Error . " [DESCRIPTION] " . $file->Rows->Row->attributes()->Description . " [CAUSE] " . $file->Rows->Row->attributes()->Cause . " [RESOLUTION] " . $file->Rows->Row->attributes()->Resolution);
}
//Copy the data
if ( !empty($file->Rows) )
{
foreach ($file->Rows->Row as $item)
{
$Data[] = array('SegmentNumber'=>$item->attributes()->SegmentNumber,'StepNumber'=>$item->attributes()->StepNumber,'Action'=>$item->attributes()->Action,'Description'=>$item->attributes()->Description,'Road'=>$item->attributes()->Road,'StepTime'=>$item->attributes()->StepTime,'StepDistance'=>$item->attributes()->StepDistance,'TotalTime'=>$item->attributes()->TotalTime,'TotalDistance'=>$item->attributes()->TotalDistance);
$TotalDistance = ($item["TotalDistance"] * 0.000621371192);
echo $TotalDistance."<br>";
Which results in the following screenshot
The problem I am having is that the echo shows that it is displaying distance for each journey step, whereas I just want the max value.
I have tried $TotalDistance = max($item["TotalDistance"]). only to get the following error:
max(): When only one parameter is given, it must be an array
Any help would be appreciated.
You can get the max value:
$value = max($array);
What you could do is put the total distance into an array first, then grab the max. Like this:
$distance_array = new array();
foreach ($file->Rows->Row as $item)
{
$Data[] = array('SegmentNumber'=>$item->attributes()->SegmentNumber,'StepNumber'=>$item->attributes()->StepNumber,'Action'=>$item->attributes()->Action,'Description'=>$item->attributes()->Description,'Road'=>$item->attributes()->Road,'StepTime'=>$item->attributes()->StepTime,'StepDistance'=>$item->attributes()->StepDistance,'TotalTime'=>$item->attributes()->TotalTime,'TotalDistance'=>$item->attributes()->TotalDistance);
$TotalDistance = ($item["TotalDistance"] * 0.000621371192);
array_push($distance_array, $TotalDistance); //add the distance to an array
}
echo max($distance_array);
http://php.net/manual/en/function.array-push.php
http://php.net/manual/en/function.max.php

Getting XML with PHP: how to get attributes from 2 nodes with same name

I am getting attributes from XML nodes and saving them to variables with a for loop as such:
for ($i = 0; $i < 10; $i++){
$group = $xml->Competition->Round[0]->Event[$i][Group];
if($group == "MTCH"){
$eventid = $xml->Competition->Round[0]->Event[$i][EventID];
$eventname = $xml->Competition->Round[0]->Event[$i][EventName];
$teamaname = $xml->Competition->Round[0]->Event[$i]->EventSelections[0][EventSelectionName];
$teambname = $xml->Competition->Round[0]->Event[$i]->EventSelections[1][EventSelectionName];
echo "<br/>" . $eventid . ": " . $eventname . ", " . $teamaname . "VS" . $teambname;
}//IF
}//FOR
I can save each Event[EventID] and each Event[EventName] but I cannot get the EventSelections[EventSelectionNames] to save.
I am guessing this is because there are multiple (2) <EventSelection>s for each <Event>, this is why I tried to get them individually uising [0] and [1].
The part of the XML file in question looks like:
<Event EventID="1008782" EventName="Collingwood v Fremantle" Venue="" EventDate="2014-03-14T18:20:00" Group="MTCH">
<Market Type="Head to Head" EachWayPlaces="0">
<EventSelections BetSelectionID="88029974" EventSelectionName="Collingwood">
<Bet Odds="2.10" Line=""/>
</EventSelections>
<EventSelections BetSelectionID="88029975" EventSelectionName="Fremantle">
<Bet Odds="1.70" Line=""/>
</EventSelections>
</Market>
</Event>
Can anyone point me in the right direction to save the EventSelectionNames to variables?
Rather than looping and checking for $group, use xpath to select data directly:
$xml = simplexml_load_string($x); // assume XML in $x
$group = $xml->xpath("/Event[#Group = 'MTCH']")[0];
echo "ID: $group[EventID], name: $group[EventName]" . PHP_EOL;
If there are always two <EventSelections>, you can:
echo "Team A: " . $group->Market->EventSelections[0]['EventSelectionName']" . PHP_EOL;
echo "Team B: " . $group->Market->EventSelections[1]['EventSelectionName']" . PHP_EOL;
Otherwise, use foreach:
foreach ($group->Market->EventSelections as $es)
$teamnames[] = $es['EventSelectionName'];
echo "There are " . count($teamnames) . "Teams:" . PHP_EOL;
foreach ($teamname as $teamname) echo $teamname . PHP_EOL;
see it in action: https://eval.in/105642
Note:
The [0] at the end of the code-line starting with $group = $xml->xpath...requires PHP >= 5.4. If you are on a lower version, update PHP or use:
$group = $xml->xpath("/Event[#Group = 'MTCH']");
$group = $group[0];
Michi's answer is more correct and better coded but I also found the adding the node 'Market' to my code worked as well:
$teamaname = $xml->Competition->Round[0]->Event[$i]->Market->EventSelections[0][EventSelectionName];
$teambname = $xml->Competition->Round[0]->Event[$i]->Market->EventSelections[1][EventSelectionName];

Having trouble searching a string

Okay I have a csv file that gets parsed and displayed. I want to make it searchable. So I have a form that accepts a user query and compares it to the array to find matches. Now here's what I have:
foreach( $last as $key=>$string ) {
$hits[$key] = strpos( strtolower( $string . " " . $first[$key] . " " . $middle[$key] ), $query );
}
Before this little snippet I force $query to lower also.
So basically this concatenates the full name, Last First Middle, and searches each array item for a match. Then if $hits[$key] != false I can say that there was a match there. So I go back and display that result from the main array of names. Hopefully that makes sense...
Now on the plus side, I will get many results that should show up. Like if I search jo, a list will come up with all of the Johnson last names.
The issue I'm having is results turning up that don't match the query or results not showing up when I know they are in the list of names. So I'll know smith john should return a result, but it will come back with no results.
This is the first time I've really worked on something with a search functionality so I want to do it right.
The strpos() function returns the index of matched substring, meaning it could possibly return 0:
strpos('foo', 'f'); // 0
If the substring is not found, it will return FALSE.
strpos('foo', 'z'); // FALSE
Because both 0 and FALSE are falsy values (meaning they both evaluate to boolean FALSE), you will need to use strict checking:
foreach( $last as $key=>$string ) {
$hits[$key] = strpos( strtolower( $string . " " . $first[$key] . " " . $middle[$key] ), $query ) !== FALSE;
}
Notice the strpos(...) !== FALSE instead of just strpos(...).
Edit (for #baudday):
Code:
<?php
$query = strtolower('Michael');
$last = array('Baier', 'Baker', 'Baker', 'Banfield', 'Banks', 'Barber');
$first = array('Michael', 'Michael', 'Stephanie', 'Christopher', 'Joseph', 'David');
$middle = array('Joseph', 'Daniel', 'Nicole', 'Phillip', 'Andrew', 'Daniel');
foreach ( $last as $key=>$string ) {
$haystack = $string . " " . $first[$key] . " " . $middle[$key] . " " . $first[$key] . " " . $middle[$key] . " " . $last[$key] . " " . $first[$key] . " " . $string . " " . $middle[$key];
$hits[$key] = strpos( strtolower( $haystack ), $query ) !== false;
}
foreach ($hits as $key => $matches) {
if ($matches) {
echo $last[$key] . ', ' . $first[$key] . ' ' . $middle[$key] . ' (key: ' . $key . ") matches the query.\n";
}
}
Output:
Baier, Michael Joseph (key: 0) matches the query.
Baker, Michael Daniel (key: 1) matches the query.

Categories