I have an array of pickers assigned to locations there could be a varying number of these.
['picker A'=>'location 1','picker B'=>'location 2','picker C' => 'location 2', 'picker D'=>'location 1']
and an array of orders which can contain products in one or more locations I have sorted the orders products into separate location arrays already by looping through all orders and products and sorting them into separate locations based on the order products subArray so one order can exist across more then one location but only contain the products in that location if that makes sense.
location 1 orders...
locatinOneOrders[0] => ['order_id','customer name','products'=>['array of products in location 1']
locatinOneOrders[1] => ['order_id','customer name','products'=>['array of products in location 1']
location 2 orders..
locatinTwoOrders[0] => ['order_id','customer name','products'=>['array of products in location 2']
locatinTwoOrders[1] => ['order_id','customer name','products'=>['array of products in location 2']
locatinTwoOrders[2] => ['order_id','customer name','products'=>['array of products in location 2']
locatinTwoOrders[3] => ['order_id','customer name','products'=>['array of products in location 1']
What I need to do is assign an equal or as equal as possible number of orders to each picker based on the location.
So in the above example Picker A and Picker D should get one order each and Picker B and Picker C should get 2 orders each, this needs to work for any number of pickers per location and any number of orders.
Could be something as simple as the following using array_chunk.
<?php
$pickers = ['picker A'=>'location 1','picker B'=>'location 2','picker C' => 'location 2', 'picker D'=>'location 1'];
$pickersByLocation = [];
foreach ($pickers as $k => $v) {
$pickersByLocation[$v][] = $k;
}
$locationOneOrders = array_fill(0, 101, 'This is an order'); //some dummy order data
$dividedOrdersLocationOne = array_chunk($locationOneOrders, count($locationOneOrders) / count($pickersByLocation['location 1']));
foreach ($pickersByLocation['location 1'] as $k => $v) {
echo "Picker {$v} assigned: \n";
print_r($dividedOrdersLocationOne[$k]);
}
/*
Picker picker A assigned:
Array
(
[0] => This is an order
[1] => This is an order
...
Picker picker D assigned:
Array
(
[0] => This is an order
[1] => This is an order
...
You might end up with a chunk that is the remainder if numbers are odd. Handle that how you like.
Related
So I have a
student model,
subject model,
marks model, which has the total score field
what I am trying to do is get the total score in an exam for each student in a class and then retrieve the results according to the highest score in the class and then position those scores as 1,2,3...
then finally get the position a single student and store it in an exam record table.
so far I was able to achieve getting the total score in an exam for each student, stored them in an array, sorted them according to the highest score,
the only issue now giving me a headache is getting the position of those scores from the array, my question is how can I get the position of a score for a student, or is there a way to add the positions to the scores and then retrieve the position for a student
For example
1 student_id => 2, total_score => 500
2 student_id => 3, total_score => 455
3 student_id => 5, total_score => 345
here is my code below, Please anyone with an idea how to solve this I need your help.
TextInput::make('position')->numeric(
function (Closure $set) {
// Get all students from class
$studentsInClass = $this->class->students;
//empty array to store student's total_score
$totalScore = [];
// loop through students get all their total_score on all subjects from mark table and sum it, then store it
in totalScore array.
foreach ($studentsInClass as $key => $student) {
$totalScore[] = array('student_id' => $student->id, 'total_score' => $student->marks->sum('total_score') );
}
// Sort scores from highest to lowest
$sortedScores= array_values(array_reverse(Arr::sort($totalScore, function ($value) {
return $value['total_score'];
})));
// get the current student Id
$id = $this->student->id;
// find a student in the array that matches the current student id and return his score.
//so this is where I would like to return the score and position of the student
$filteredArray = Arr::where($sortedScores, function ($value, $key) use ($id) {
return $value['student_id'] == $id;
});
}
)->disabled(),
if you dd($sortedScores)
You have a two-dimensional array.
$sortedScores = [
['student_id' => 2, 'total_score' => 443],
['student_id' => 4, 'total_score' => 410],
['student_id' => 1, 'total_score' => 371],
['student_id' => 3, 'total_score' => 170],
];
The index of each row is already consecutive from 0-3. I think you want to add a rank to the rows.
foreach($sortedScores as $idx => $row)
$sortedScores[$idx]['rank'] = $idx+1;
//test output
var_export($sortedScores);
Output:
array (
0 =>
array (
'student_id' => 2,
'total_score' => 443,
'rank' => 1,
),
1 =>
array (
'student_id' => 4,
'total_score' => 410,
'rank' => 2,
),
2 =>
array (
'student_id' => 1,
'total_score' => 371,
'rank' => 3,
),
3 =>
array (
'student_id' => 3,
'total_score' => 170,
'rank' => 4,
),
)
If you want rank to start at 0, just assign $idx.
Try on https://3v4l.org/9Dv7D
I hope this helps and that I understood your problem correctly.
To find the key for a specific value in a multidimensional array see 'PHP Multidimensional Array Searching (Find key by specific value)'
You can use the array_search() function. This will either return the key of the value you are looking for or false if it is not in the array.
$letters = ['a', 'b', 'c', 'd'];
$key = array_search('b', $letters);
//In this case $key will equal to 2.
Presuming that $filteredArray contains a single item, then the first key should be the student's position in the sorted array.
$position = array_keys($filteredArray)[0];
Writing in PHP, I have 2 arrays, each created from SQL queries.
The first query runs through a table that has multiple pieces of data that correspond to various quiz attempts. The table has a column for the user's Email, the activity ID (which represents a quiz attempt) and another 2 columns for data relating to the attempt (for example 'percentage achieved' or 'quiz ID'):
UserEmail ActID ActKey ActMeta
joB#gm.com 2354 Percentage 98
joB#gm.com 2354 Quiz ID 4
boM#hm.com 4567 Percentage 65
boM#hm.com 4567 Quiz ID 7
Once queried, this first array ($student_quiz_list) stores the selected data in the form of
[[UserEmail, ActID, ActKey, ActMeta], [UserEmail, ActID, ActKey, ActMeta], [UserEmail, ActID, ActKey, ActMeta]...]
where each pair of sub-arrays corresponds to a single quiz attempt.
The second table that is queried has two columns that relate to the quizzes themselves. The first column is the Quiz ID and the second is the Quiz name.
Quiz ID Quiz Name
4 Hardware
7 Logic
Once queried, this second array ($quiz_list) stores the selected data in the form of
[[ID, Name], [ID, Name]...]
What I need to do is create a 3rd array (from the 2 above) which holds the user's email and percentage score
[email, percentage], [email, percentage]...]
but with each sub-array corresponding to a unique actID (so basically the user's percentage in each quiz they attempted without duplicates) and (this is the challenging bit) only for quizzes with certain ID values, in this case, let's say quiz ID 4.
In PHP, what would be the most efficient solution to this? I continually create arrays with duplicates and cannot find a neat solution which provides the outcome desired.
Any help would be greatly received.
Try this code as the example and let me know.
$student_quiz_list=array(
array(
'UserEmail'=>'joB#gm.com','ActID'=>'2354','ActKey'=>'Percentage','ActMeta'=>'90',
),
array(
'UserEmail'=>'joB#gm.com','ActID'=>'2354','ActKey'=>'QuizID','ActMeta'=>'4',
),
array(
'UserEmail'=>'boM#hm.com','ActID'=>'4567','ActKey'=>'Percentage','ActMeta'=>'98',
),
array(
'UserEmail'=>'boM#hm.com','ActID'=>'4567','ActKey'=>'QuizID','ActMeta'=>'7',
),
);
$final_array=array();
foreach( $student_quiz_list as $row){
if($row['ActKey']=='Percentage'){
$final_array[]=array('UserEmail'=>$row['UserEmail'],
'ActMeta'=>$row['ActMeta']
) ;
}
}
echo"<pre>"; print_r($final_array); echo"</pre>";
As commenter #Nico Haase suggested, you can do most of the logic in SQL. You didn't respond to my comment, so I suppose a user can have multiple attempts per quiz ID:
SELECT
UserEmail,
ActMeta
FROM
your_table # replace with your table name
WHERE
ActKey = 'Percentage'
AND ActID IN (
# subselection with table alias
SELECT
t2.ActID
FROM
your_table t2 # replace with your table name
WHERE
t2.ActKey = 'Quiz ID'
AND t2.ActMeta = 2 # insert your desired quiz ID here
AND t2.ActID = ActID
)
(Query tested with MySQL/MariaDB)
For the case that you cannot change the SQL part, here is how you can process your data in PHP. But consider that a large dataset could exceed your server capabilities, so I would definitely recommend the solution above:
// Your sample data
$raw = [
['UserEmail' => 'joB#gm.com', 'ActID' => 2354, 'ActKey' => 'Percentage' , 'ActMeta' => 98],
['UserEmail' => 'joB#gm.com', 'ActID' => 2354, 'ActKey' => 'Quiz ID', 'ActMeta' => 4],
['UserEmail' => 'joB#gm.com', 'ActID' => 4567, 'ActKey' => 'Percentage' , 'ActMeta' => 65],
['UserEmail' => 'joB#gm.com', 'ActID' => 4567, 'ActKey' => 'Quiz ID', 'ActMeta' => 7],
];
// Extract the corresponding ActIDs for a QuizID
$quiz_id = 4;
$act_ids = array_column(
array_filter(
$raw,
function($item) use ($quiz_id) {
return $item['ActMeta'] == $quiz_id;
}
),
'ActID'
);
// Get the entries with ActKey 'Percentage' and an ActID present in the previously extracted set
$percentage_entries = array_filter(
$raw,
function($item) use ($act_ids) {
return $item['ActKey'] === 'Percentage' && in_array($item['ActID'], $act_ids);
}
);
// Map over the previous set to get the array into the final form
$final = array_map(
function($item) {
return [$item['UserEmail'], $item['ActMeta']];
},
$percentage_entries
);
PHP 7
I am trying to list, in a drop down menu button that is dynamically driven, the days of the week if they are present in a query. However I only want one result to print per day even though there will be more.
For example: if there are 12 customers assigned on a Monday, I only want the one 'Monday' result to print in my drop down menu. This is an example of how the drop down button should perform in regards to listing days if present in the query. #note that the Customer table has 2 entries for Wed as indicated in the Customers button drop down, but I only want Wed listed once in the drop down for Routes.
*Basically the query gets * from a table where a user_id = 'session_id', this orders by a day column that is in numerical form in the DB; 1-7 for Mon-Sun.
$sql = "
SELECT *
FROM `customers`
WHERE `users_id` = '1'
ORDER BY `cust_route_day` ASC
LIMIT 0 , 30";
$cust = new User;
$results = $cust->db->query($sql);
User comes from a user class that connects to DB and performs various queries.
Definitions and declarations.
$custName = array();
$custRouteDay = array();
$custID = array();
while ($row = $results->fetch_assoc())
{
$custName[] = $row['cust_first_name'].' '.$row['cust_last_name'];
$custRouteDay[] = $row['cust_route_day'];
$custID[] = $row['cust_id'];
}
define("CUSTID", $custID);
define("USER_TASKS", [
'Task Info' => 'Task Info',
'Task Time' => 'Task Time',
'Customer Route Info' => 'Customer Route Info',
'Set Alert' => 'Set Alert'
]);
define("CUSTOMERS", $custName);
define("USER_TASKS", $userTasks);
// Assign the abbr value of day ex: 'Wed' to numerical value from DB ex: '2'
foreach(CUST_ROUTE_DAY as $key => $value){
$newKey .= ROUTEDAY[$value]." ";
$custRouteKeyArray = explode(" ",$newKey);
}
define("NAVICONS", [
"glyphicon glyphicon-user",
"glyphicon glyphicon-road",
"glyphicon glyphicon-tasks",
"fa fa-sitemap",
"fa fa-globe"
]);
define( "STYLE", [
"fixed-bottom" => "navbar navbar-default navbar-fixed-bottom",
"fixed-top" => "navbar navbar-default navbar-fixed-top",
"default" => "navbar navbar-default"
]);
define("NAVBTNS", [
"Customers"=>CUSTOMERS,
"Route Info"=>$custRouteKeyArray,
"Tasks"=>USER_TASKS,
"Networking",
"Maps"
]);
The defined array NAVBTNS:
Array ( [0] => John Banner [1] => Dale Landry [2] => Bill Childers [3] => Darren Little [4] => Gary Garland ) Array ( [0] => Mon [1] => Wed [2] => Wed [3] => Thur [4] => Fri [5] => ) Array ( [Task Info] => Task Info [Task Time] => Task Time [Customer Route Info] => Customer Route Info [Set Alert] => Set Alert ) NetworkingMaps
The function that creates the Navigation menu btns and drop down btn. Basically if the array consists of sub arrays, create a drop down button and assign the key and values appropriately.
function construct_navbar_buttons(){
//because key values in the parent array are mixed numerical and char values
//define and increment $i each time through the loop for NAVICONS class values and page number key
$i = 0;
//Start the post variable that will hold the result string $btns <ul>
$btns = '<ul class="nav navbar-nav">';
foreach(NAVBTNS as $k => $v){//$k holds index or e.g. Customers
if(is_array($v)){//go over subarray else print button see //we have a string value
$filtered = array_filter($v);//array_filter to remove null values
if(empty($filtered)) {
$btns .= '<li><i class="'.NAVICONS[$i].'"></i> '.$v.'</li>';
}else{//start drop down here
$btns .= '<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="">
<i class="'.NAVICONS[$i].'"></i> '.$k.' <span class="caret"> </span>
</a>
<ul class="dropdown-menu dropdown-user">';
foreach($v as $key => $value){//loop through results of child array
if(in_array($v[$key], $v)){ //locate instance where key exists and print list-item a tag button in drop-down
################################################################
## need logic to go over first instance of a value within the ##
## parent array to print only that first value in the results ##
################################################################
$btns .= '<li>'.$v[$key].'</li>';
}
}
$btns .= "</ul>\n</li>";//close the parent UL and LI tags
}
}else{//we have a string value
//do stuff example data: Tasks - key here seems aways a index number
$btns .= '<li><i class="'.NAVICONS[$i].'"></i> '.$v.'</li>';
}
$i++;print_r($v);
}
$btns .= '</ul>';
return $btns;
}
Tried using array_search, but this is not giving me the results I hoped for
$d = array_search($value, $v);
if($d = ROUTEDAY[$i]){
echo $value;
}
$day = array("Mon","Tue","Wed","Thur","Fri","Sat","Sun");
if($d = $day[$i]){
echo $day[$i];
}
ROUTEDAY is a defined variable that holds the days of the week with keys values, gives me the following results on a simple echo.
1 - MonWedWedThurFriTask InfoTask TimeCustomer Route InfoSet Alert
2 - MonTueWed
I thought array_search only gave you the first occurrence of a value in an array.
I have tried creating separate foreach loops for each instance of an array, but that complicates things and I wish to get this done using the two foreach loops only. I am so close to getting this. If anyone could help I would be very grateful.
OK for the sake of others that may be searching for a similar answer, I figured out how to make this work.
I changed the redefined array to assign abbr. to numerical value for week day, here:
foreach(CUST_ROUTE_DAY as $key => $value){
$newKey .= ROUTEDAY[$value]." ";
$custRouteKeyArray = explode(" ",$newKey);
}
To the following:
$day = array("Mon"=>0,"Tue"=>1,"Wed"=>2,"Thur"=>3,"Fri"=>4,"Sat"=>5,"Sun"=>6);
$d = array();
foreach($day as $days=>$key){
if(in_array($key, $custRouteDay)){
$d[] = ROUTEDAY[$key];
}
}
This gives me:Array ( [0] => Mon [1] => Wed [2] => Thur [3] => Fri )
I use this value in my NAVBTNS array:
define("NAVBTNS", [
"Customers"=>CUSTOMERS,
"Route Info"=>$d,
"Tasks"=>USER_TASKS,
"Networking",
"Maps"
]);
*Problem solved!
I am build a multidimension array from data that has a multiple entries but some entries have the same value;
id name delivery# weight time
--------------------------------------------
12 test 112233 45 now
13 test 112234 456 now
14 testA 112245 33 later
15 testB 334421 334 later
...
...
and foreach id I push to array like so;
array_push($arraydata, array(
"id" => $id,
"name" => $name,
"delivery" => $delivery,
"weight" => $weight,
"time" => $time
));
and later I use to loop through it;
foreach($arraydata as $arraydataItem) {
//do stuff...
//test appears twice - echo count & delivery values
//testA once - echo count
//testB once - echo count
}
Basically I want check how many times the same name value appears and add the weight values together for a total.
As then for each "delivery" with the same "name" divide the delivery weight by the total weight of "name" and get the percentage which I will use for calculating the percentage of the total cost of "name"..
Instead of creating that associative array using array_push(), you should create a multidimensional array like this,
$arraydata[$name][] = array('id' => $id, 'delivery' => $delivery, 'weight' => $weight, 'time' => $time);
And as per your question,
Basically I want check how many times the same name value appears and add the weight values together for a total.
Simply use a foreach loop to loop through $arraydata array and display count and total weight associated for each name, like this:
foreach($arraydata as $key => $arraydataItem){
// Display count and total weight associated for each name
echo $key . ": (count: " . count($arraydataItem) . ", total weight: " . array_sum(array_column($arraydataItem,'weight')) . ")<br />";
}
This will output:
test: (count: 2, total weight: 501)
testA: (count: 1, total weight: 33)
testB: (count: 1, total weight: 334)
Moreover, you can tweak this code to fulfil your further requirements.
Note: If you want to see the structure of $arraydata array, do var_dump($arraydata);
I'd like to build a simple shopping cart using arrays. I need to display each unique item in the shopping cart aswell as the quantity of each item along side.
My initial cart array might look like this:
$cart=
array(
array(2003,100,"Table")
,array(2003,100,"Table")
,array(2003,100,"Table")
,array(2004,200,"Chair")
,array(2004,200,"Chair")
);
The first value in each array is the product_id, then the price & then the product name.
How do I print each unique item once aswell as the quantity of each along side?
Thanks in advance.
$new_cart = array();
foreach($cart as $product) {
if(!isset($new_cart[$product[0]])) {
$new_cart[$product[0]] = array('quantity' => 1, 'label' => $product[2], 'price' => $product[1]);
}
else {
$new_cart[$product[0]]['quantity']++;
}
}
I strongly suggest using associative arrays for this though. Your problem is the way you are storing the values. Try using something like this:
$cart_items = array(
2004 => array('quantity' => 3, 'label' => 'Leather Chair', 'price' => 200),
2901 => array('quantity' => 1, 'label' => 'Office Desk', 'price' => 1200),
);
When a user updates a quantity or adds an existing product simply increment the quantity.
You could simply iterate the array and use the product ID as key to count the amounts:
$amounts = array();
foreach ($cart as $item) {
if (!isset($amounts[$item[0]])) $amounts[$item[0]] = 0;
$amounts[$item[0]]++;
}
But it would be easier if your cart just stores the product IDs and amounts, so:
array(
2003 => 3,
2004 => 2
)
This is actually what the algorithm above is doing. But with this, you have all the information you need (product ID and amount).