I'm creating a lottery to pair up people. So I want a way to shuffle the strings in an array where no item ends up on the same place. (You can't pair up with yourself)
public function shuffleSantas(){
$query = $this->db->get('person');
$givers = array();
$recievers = array();
foreach($query->result() as $row):
$givers[] = $row->name;
//here i want a random order, but no name can be on the same place as in $givers!
$recievers[] = '';
endforeach;
shuffle the array once and then pair up the first element with the second, the second with the third etc. and the last with the first.
$src = $query->result();
$givers = array();
$receivers = array();
foreach ($src as $idx=>$first_person){
$count = 0; //infinite loop guard
do{
++$count;
$sec_idx = rand(0,count($src)-1);
$second_person = $src[$sec_idx];
} while ($second_person==$first_person && $count<5);
$givers[] = $first_person;
$receivers[] = $second_person;
}
In this case one will be able to receive from one person and to give to other person. Is it OK? Also, this algorithm is not optimal and will definitely fall into infinity loop if there is only one person in an array.
If think there is no built-in function in PHP to shuffle that way. You have to write your own function.
Related
PHP isn't returning unique items between assigned_IPs and IP_array.
I need an unique output.
I already tried merging arrays and comparing them.
$ips2 = array();
while ($row = mysql_fetch_assoc($result))
{
$ips2[] = $row["ipaddr"];
}
$assigned_ips = $ips2;
$ip_array = explode("\n",$ips);
$ips_left = array_diff($ip_array,$assigned_ips);
I need to return an unique array once PHP compares the 2 item lists.
Lucky for you, PHP has an array_unique() function for just such a purpose! You could perform it on both of the compared arrays before array_diff(), but I am pretty sure best (an most efficient) practice would be to perform it only once when you already have the results:
$ips2 = array();
while ($row = mysql_fetch_assoc($result))
{
$ips2[] = $row["ipaddr"];
}
$assigned_ips = $ips2;
$ip_array = explode("\n",$ips);
$ips_left = array_unique(
array_diff($ip_array,$assigned_ips)
);
Just for the sake of completeness, here is an alternative way that could be more efficient if you have a large number of duplicates that would bog down the array_diff() function:
$ips2 = array();
while ($row = mysql_fetch_assoc($result))
{
$ips2[] = $row["ipaddr"];
}
$assigned_ips = $ips2;
$ip_array = explode("\n",$ips);
$ips_left = array_diff(
array_unique($ip_array)
array_unique($assigned_ips)
);
I have multiple dates to calculate on database. They are fetched and stored in an array.
How can I have variables for each of the returned values, since I don't know how many of the dates are returned?
Here is what I tried so far:
$get_status = $truckerController->status($gid);
$active_days = 0;
$active_d = array();
foreach ($get_status as $trucker) {
$active_d[] = $trucker->date;
}
list($date1, $date2) = $active_d;
So what I want is to have more than two or three parameters inside list() based on the array value size. Please help me out or suggest other ways to handle this issue.
Not sure if the whole approach is correct, but you can try with something like this.
$get_status = $truckerController->status($gid);
$active_days = 0;
$active_d = array();
$i = 0;
foreach ($get_status as $trucker) {
$i++;
$active_d["date".$i] = $trucker->date;
}
extract($active_d);
http://php.net/manual/en/function.extract.php
I'm trying to sort data alphabetically by the COMPANY NAME from a flat file. I was thinking that a simple sort would handle this, but I was wrong. I now think that I need to use usort and cmp and then create another temp array. How can I accomplish this?
This is my current code.
$data_file = fopen($data_file_url, "r");
fgets($data_file); // IGNORE FIRST LINE IN FLATFILE - column names
while (!feof($data_file) ) {
$data_lines = fgets($data_file);
$data_ele = explode('|', $data_lines);
$company_name = $data_ele[0];
$section = $data_ele[1];
$category = $data_ele[2];
$service = $data_ele[3];
$service = substr_replace($service,"",-1); // trim last char
}
You should first store all elements in a big array and afterwards sort it using a callback:
$data_file = fopen($data_file_url, "r");
fgets($data_file); // IGNORE FIRST LINE IN FLATFILE - column names
$companies = array();
while (!feof($data_file) ) {
$data_lines = fgets($data_file);
$data_ele = explode('|', $data_lines);
$row = array();
$row['company_name'] = $data_ele[0];
$row['section'] = $data_ele[1];
$row['category'] = $data_ele[2];
$row['service'] = $data_ele[3];
$row['service'] = substr_replace($row['service'],"",-1); // trim last char
$companies[] = $row;
}
usort($companies, function ($a, $b) {
return strcmp($a['company_name'], $b['company_name']);
});
Please note: I'm using an anonymous function, introduced in PHP 5.3.0.
I would imporove upon Beats answer only by using the company name as a key in the array.
If you have multiple entries per company have a sub array.
By using the key as array it is already indexed when inserted.
I believe its faster.
You could also use fgetcsv here, which is also probably a little faster.
I have one array which have the right order of the keys,
For example,
$array_keysorder=([0]=>"Fire",[1]=>"Sky",[2]=>"Third")
//Array i want to sort,after appending the order is messed up
$tosortarray=(['Sky']=>array(array()...),['Third']=>array(),['Fire']=>array())
//This is how i want the final array to look like
$Final=(['Fire']=>array(), ['Sky']=>array(array()...),['Third']=>array())
What about rebuilding the array?
Edit.. I added some commenting..
<?php
$array_keysorder[] = "Fire";
$array_keysorder[] = "Sky";
$array_keysorder[] = "Third";
print_r($array_keysorder);
$bad_array[Sky] = "data1";
$bad_array[Third] = "data2";
$bad_array[Fire] = "data3";
echo "<br>";
print_r($bad_array);
//This count cycles through the sort order, 0 = Fire, 1 = Sky, etc.
$key = 0;
//Cycle through array. $row isn't used.
foreach($bad_array as $row)
{
//$temp_val will store the key name ie "Fire".
$temp_val = $array_keysorder[$key];
//Create a organized array with the correct order of the keys
$good_array[$temp_val] = $bad_array[$temp_val];
//Increase the key to the next one.
$key++;
}
echo "<br>";
print_r($good_array);
?>
Im looping through some XML nodes, and say i have between 1 and 200 of these nodes.
How can i "randomly" select a maximum of 10 of these nodes. It has to be as most ten, but as few as 1.
This is what im working with now...
$i = 0;
foreach ($butters->users->user as $user) {
if($i==10) break;
$id = $user->id;
$name = $user->screen_name;
$profimg = $user->profile_image_url;
echo "things";
$i++;
}
The difficulty is that i don't know how many i will have, but would like the pool from which i select my "random" 10 to be from the entirety of however many are present.
$randomPool = array_rand ( $butters->users->user, 10 );
I'd get the 10 random indexes, then loop through those and get the nodes.
$indexes = array();
for($i = 0; $i< 10; $i++){
$indexes[] = rand(0, $butters->users->length);
}
foreach($indexes as $index){
$user = $butters->users->item($index);
//do whatever with $user
}
You'll need to add a check to make sure that you have not already got the index when you add it to the $indexes array.
You could put this into one command, however you may end up with duplicates (unlikely depending on the amount of elements, but possible...
for($i = 0; $i< 10; $i++){
$user = $butters->users->item(rand(0, $butters->users->length));
//do something with $user
}
Put all users in an array, shuffle it and grab the first ten items:
$users = array[];
foreach ($butters->users->user as $user) {
$users[] = &$user;
}
shuffle($users);
$tenRandomUsers = array_slice($users, 0, 10);
Maybe you can shorten the first step with just $users = (array) $butters->users->user.
Create a random object (don't know the PHP specific code) then call it and compare with 10 / (total in the set). This means you should in theory select 10%, however it could be less, and your exiting code stops it from selecting more.
Assuming you are using SimpleXML, you could use an XPath to get all the users. This will return an array and from that it should be cake.
Something like this should do:
$users = $xml->xpath('//butters/users/user');
$random = array_rand($users, 10);
Someone might want to correct me on the Xpath though. Doing it from memory
if you have some sort of strange self-implemented data structure for $users you might want to use reservior sampling -- Efficiently selecting a set of random elements from a linked list