I have this array built from a function that sorts allowed or valid url slugs and their ids into another array. I can call the current category id by passing the url slug to the category. Now I need to get the children category ids (if any) so i can call the appropriate items from the database for display purpose.
Heres an example of the array:
Array (
[radios] => 1
[radios/motorola] => 2
[radios/motorola/handheld] => 3
[radios/motorola/mobile] => 4
[radios/icom] => 5
[radios/icom/handheld] => 6
[radios/icom/mobile] => 7
[radios/mics-and-speakers] => 8
[radios/mounts] => 9
[radios/radio-other] => 10
[misc] => 11
[misc/led] => 12
[phones] => 13
[phones/samsung] => 14
[phones/lg] => 15
[phones/motorola] => 16
[phones/huawei] => 17
[phones/blackberry] => 18
[phones/flip] => 19
[boosters] => 20
[boosters/standalone] => 21
[boosters/indoor-antenna] => 22
[boosters/outdoor-antenna] => 23
[boosters/connections] => 24
[accessories] => 25
[accessories/cases] => 26
[accessories/other] => 27
[internet] => 28
[internet/fusion] => 29
[internet/point-to-point] => 30
[internet/hotspots] => 31
[internet/gateways] => 32
[internet/switches] => 33
[cameras] => 34
[cameras/complete-kits] => 35
[cameras/additional-cameras] => 36
[cameras/other] => 37
);
As you can see, each result points to the category ID of that group. If i visit the following url:
http://example.com/store/cameras
I can print out that THE PATH CURRENTLY IS: 34 which is correct. Since It has children under it, I also need their ID's and the ID's of any of their children, etc etc. That way on radios, i can show ALL of the sub category items, and on radios/motorola i am only showing the Motorola based items and its children, and such down the line.
If there an easy way, using this array I have now, to sort the children (if any) all the way down and get back just their id's (preferably in a new array) for showing database items?
You might want to create a function like this to filter your array,
function filterArray($array, $term) {
$pattern = "/\b" . str_replace($term, '/', '\/') . "\b/i";
foreach($array as $key => $value) {
if(preg_match($pattern, $key)) {
/* Following condition makes sure that your search
will match starting from the beginning. */
if (stripos(trim($key), $term) === 0){
$filtred[] = $value;
}
}
}
}
Then call the above function with the $array and your search $term.
filterArray($array, 'radios') will give you this,
Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 [5] => 6 [6] => 7 [7] => 8 [8] => 9 [9] => 10 )
filterArray($array, 'radios/motorola') will give you this,
Array ( [0] => 2 [1] => 3 [2] => 4 )
And so on.. I hope this helps.
You can maybe try double layer array, so that you can store values like this,
Array (
[name] => John
[surname] => Smith
[contact] => Array (
[address] => 18 Maple Street
[number] => 555 477 77 77
)
)
This way if you need to print something from "contact" you can use a loop and print all childs of contact field.
I am stumped about how to go about checking to see if multiple *date/time value -ranges- (meaning: start and end times) are in conflict with one another.
Summary & samples of data I need to work with.
I have an (app) events table, that is used to create a form for the user to go through and check off (checkboxes) all the sessions/events they attended.
The names of the checkboxes are generated using info about the session. (month/day start/end times along with a session id)
ie: hours_9_5_p02_800_845
9 = month
5 = date
p02 = session id/event code
800 = start time
845 = end time
all delimited by an underscore ("_")
If the user checks (and submits) multiple sessions, there will be many of these values to check for a time conflict..
hours_9_5_p08_755_800
hours_9_5_p02_800_845
hours_9_5_p02_800_855
hours_9_5_p03_800_845
hours_9_5_p04_820_835
hours_9_5_p04_845_900
hours_9_5_REG_900_915
hours_9_5_REG_1300_1305
hours_9_5_REG_1310_1335
hours_9_5_REG_1320_1335
The above is an example of the fieldlist/array that I 'could' get as a user selection/submission that I need to check for any possible conflicts (obviously the user couldnt be two places at once) :) And the above have many/several overlapping of just the same exact time slots selected.
** I am open to either PHP, (checking after the user submits) or javascript/jQuery (if it can do the date/time RANGE conflict checking, it might be easier to then highlight those rows/elements on the page if done on the front end)
I'd image, first you need to parse those checkbox names/strings from the fieldlist array...
which I have done like so: (php)
function conflictParse($delimiter, $targetString){
//echo 'fired';
$breakDown = explode($delimiter, $targetString);
$startTime = substr_replace($breakDown[4] , ':', -2, 0);
$endTime = substr_replace($breakDown[5] , ':', -2, 0);
$startString = "$breakDown[1]/$breakDown[2]/2015 $startTime";
$endString = "$breakDown[1]/$breakDown[2]/2015 $endTime";
$startFormat = strtotime($startString);
$endFormat = strtotime($endString);
$start = date('m/d/Y G:i',$startFormat);
$end = date('m/d/Y G:i',$endFormat);
return "Session Times: $start -- $end <br>";
}
echo conflictParse('_','hours_9_5_p02_800_845');
but I am not clear on HOW to go about using this RANGE of a date start & end time to check against MULTIPLE other date start/end time RANGES?
maybe just sticking with having PHP parse/check conflict upon submit and then return some array of the (original) names page to the page (for some jQuery to use and highlight the elements..etc (but I can handle that aspect later.. for right now I am need help on how I can get the above parse 'date/time' start/end range values checked for conflicts against other 'date/time' start/end range values
update:
Here is the current nested associative array I have to work with for comparing:
Array (
[0] => Array (
[id] => hours_9_9_p02_800_845
[fullStart] => 09/09/2015 8:00
[fullEnd] => 09/09/2015 8:45
[month] => 9
[date] => 9
[session_code] => p02
[start] => 8:00
[end] => 8:45
[hasConflict] => false
)
[1] => Array (
[id] => hours_9_9_p02_800_855
[fullStart] => 09/09/2015 8:00
[fullEnd] => 09/09/2015 8:55
[month] => 9
[date] => 9
[session_code] => p02
[start] => 8:00
[end] => 8:55
[hasConflict] => false
)
[2] => Array (
[id] => hours_9_9_p03_800_845
[fullStart] => 09/09/2015 8:00
[fullEnd] => 09/09/2015 8:45
[month] => 9
[date] => 9
[session_code] => p03
[start] => 8:00
[end] => 8:45
[hasConflict] => false
)
[3] => Array (
[id] => hours_9_9_p04_820_830
[fullStart] => 09/09/2015 8:20
[fullEnd] => 09/09/2015 8:30
[month] => 9
[date] => 9
[session_code] => p04
[start] => 8:20
[end] => 8:30
[hasConflict] => false
)
[4] => Array (
[id] => hours_9_9_p04_845_900
[fullStart] => 09/09/2015 8:45
[fullEnd] => 09/09/2015 9:00
[month] => 9
[date] => 9
[session_code] => p04
[start] => 8:45
[end] => 9:00
[hasConflict] => false
)
[5] => Array (
[id] => hours_9_9_REG_1300_1315
[fullStart] => 09/09/2015 13:00
[fullEnd] => 09/09/2015 13:15
[month] => 9
[date] => 9
[session_code] => REG
[start] => 13:00
[end] => 13:15
[hasConflict] => false
)
[6] => Array (
[id] => hours_9_9_REG_1300_1330
[fullStart] => 09/09/2015 13:00
[fullEnd] => 09/09/2015 13:30
[month] => 9
[date] => 9
[session_code] => REG
[start] => 13:00
[end] => 13:30
[hasConflict] => false
)
)
I need to convert your js functions over to PHP and of course use the fullStart/fullEnd variables in my time compares I guess..??
(but your function is still confusing me as I see references to event1, event 2.. (to match your example)..
update 2:
The above is my object/array (associative array) that I got from selecting some check boxes, and submitting my form...
Here is my attempt to convert your JS code to PHP based [with some update variablenames]: (and the commented out lines just to try and get some sort of output somewhere)
print_r($conflict_list);
function checkFirst($cf_presX, $cf_presY) {
//$cf_presX['fullStart'] < $cf_presY['fallStart'] ? checkConflict($cf_presX, $cf_presY) : checkConflict($cf_presY, $cf_presX);
echo 'Pres Check: '.$cf_presX[0] . '<br>';
echo 'Pres Check: '.$cf_presY[0] . '<br>';
/*
function checkConflict ($cc_presX, $cc_presY) {
if ($cc_presX.['fullEnd'] > $cc_presY.['fullStart']) {
$cc_presX.['hasConflict'] = true;
$cc_presY.['hasConflict'] = true;
}
}
*/
}
function setConflicts($events) {
for ($i = 0; $i < count($events); $i++) {
for ($j = 0; $i < count($events); $j++) {
// if it is not the same event
// if (i !== j) is the same $age['Peter']
if ($events[$i]['id'] !== $events[$j]['id']) {
checkFirst($events[$i], $events[$j]);
}
}
}
}
setConflicts($conflict_list);
I just keep getting a loop with undefined offset: (counting up to the 100k+ mark)
Notice: Undefined offset: 0 in
C:\wamp\www\projects\misc\conflict_check_new.php on line 49 Pres
Check:
Notice: Undefined offset: 0 in
C:\wamp\www\projects\misc\conflict_check_new.php on line 50 Pres
Check:
Notice: Undefined offset: 0 in
C:\wamp\www\projects\misc\conflict_check_new.php on line 49 Pres
Check:
The same logic could apply in PHP, but assuming you can get your events out into JavaScript and create an array of objects with start and end dates like so:
var events = [
{
id: 'event1',
start: new Date('1/1/1 5:00'),
end: new Date('1/1/1 6:00'),
hasConflict: false
},
{
id: 'event2',
start: new Date('1/1/1 5:30'),
end: new Date('1/1/1 6:30'),
hasConflict: false
},
{
id: 'event3',
start: new Date('1/1/1 7:30'),
end: new Date('1/1/1 8:30'),
hasConflict: false
}
]
You can compare events to see if the one that starts first, has an end time that's later the second one's start time.
function checkFirst (event1, event2) {
event1.start < event2.start
? checkConflict(event1, event2)
: checkConflict(event2, event1)
function checkConflict (first, second) {
if (first.end > second.start) {
first.hasConflict = second.hasConflict = true
}
}
}
Then you can check events against each other. Here's a not particularly efficient, but at least suitable loop:
function flagAllEventsWithConflicts (events) {
events.forEach(event1 => {
events.forEach(event2 => {
event1.id !== event2.id && checkFirst(event1, event2)
})
})
}
Update: The above function can also be written as a nested for loop:
function flagAllEventsWithConflicts (events) {
for (var i = 0; i < events.length; i++) {
for (var j = 0; j < events.length; j++ {
// if it is not the same event
// if (i !== j) is the same
if (events[i].id !== events[j].id) {
checkFirst(events[i], events[j])
}
}
}
}
Then check to see if hasConflict is true or false:
flagAllEventsWithConflicts(events)
console.table(events)
Run this fiddle and checkout the console
I am trying to calculate the winning order of golfers when they are tied in a competition.
These golf competitions are using the "stableford" points scoring system, where you score points per hole with the highest points winning. Compared to normal golf "stroke play" where the lowest score wins (though this also has the countback system, only calculating the lowest score in the event of a tie...)
The rules are to use a "countback". i.e., if scores are tied after 9 holes, the best placed of the ties is the best score from the last 8 holes. then 7 holes, etc.
The best I can come up with is 2 arrays.
An array with all the players who tied in a given round. ($ties)
One which has the full score data in (referencing the database playerid) for all 9 holes. ($tie_perhole)
I loop through array 1, pulling data from array 2 and using the following formula to create a temporary array with the highest score:
$max = array_keys($array,max($array));
If $max only has 1 item, this player is the highest scorer. the loop through the first array is "by reference", so on the next iteration of the loop, his playerid is now longer in the array, thus ignored. this continues until there is only 1 playerid left in the first array.
However, it only works if a single player wins in each iteration. The scenario that doesn't work is if a sub-set of players tie on any iterations / countbacks.
I think my problem is the current structure I have will need the original $ties array to become split, and then to continue to iterate through the split arrays in the same way...
As an example...
The $ties array is as follows:
Array
(
[18] => Array
(
[0] => 77
[1] => 79
[2] => 76
[3] => 78
)
)
The $tie_perhole (score data) array is as follows:
Array
(
[18] => Array
(
[77] => Array
(
[9] => 18
[8] => 16
[7] => 14
[6] => 12
[5] => 10
[4] => 8
[3] => 6
[2] => 4
[1] => 2
)
[79] => Array
(
[9] => 18
[8] => 17
[7] => 15
[6] => 14
[5] => 11
[4] => 9
[3] => 7
[2] => 5
[1] => 3
)
[76] => Array
(
[9] => 18
[8] => 16
[7] => 14
[6] => 12
[5] => 10
[4] => 8
[3] => 6
[2] => 4
[1] => 2
)
[78] => Array
(
[9] => 18
[8] => 17
[7] => 15
[6] => 13
[5] => 11
[4] => 9
[3] => 7
[2] => 5
[1] => 3
)
)
)
So in this competition, player's 78 and 79 score highest on the 8th hole countback (17pts), so 1st and 2nd should be between them. Player 79 should then be 1st on the 6th hole countback (14pts, compared to 13pts). The same should occur for 3rd and 4th place with the 2 remaining other players.
There are other scenarios that can occur here, in that within a competition, there will likely be many groups of players (of different amounts) on different tied points through the leaderboard.
Also note, there will be some players on the leaderboard who are NOT tied and stay in their current outright position.
The basics of the working code I have is:
foreach ($ties as $comparekey => &$compareval) {
$tie_loop = 0;
for ($m = 9; $m >= 1; $m--) {
$compare = array();
foreach ($compareval as $tie) {
$compare[$tie] = $tie_perhole[$comparekey][$tie][$m];
}
$row = array_keys($compare,max($compare));
if (count($row) == 1) {
$indexties = array_search($row[0], $ties[$comparekey]);
unset($ties[$comparekey][$indexties]);
// Now update this "winners" finishing position in a sorted array
// This is a multidimensional array too, with custom function...
$indexresults = searchForId($row[0], $comp_results_arr);
$comp_results_arr[$indexresults][position] = $tie_loop;
$tie_loop++;
}
// I think I need conditions here to filter if a subset of players tie
// Other than count($row) == 1
// And possibly splitting out into multiple $ties arrays for each thread...
if (empty($ties[$comparekey])) {
break;
}
}
}
usort($comp_results_arr, 'compare_posn_asc');
foreach($comp_results_arr as $row) {
//echo an HTML table...
}
Thanks in advance for any helpful insights, tips, thoughts, etc...
Robert Cathay asked for more scenarios. So here is another...
The leaderboard actually has more entrants (player 26 had a bad round...), but the code i need help with is only bothered about the ties within the leaderboard.
Summary leaderboard:
Points Player
21 48
21 75
20 73
20 1
13 26
This example produces a $tie_perhole array of:
Array
(
[21] => Array
(
[75] => Array
(
[9] => 21
[8] => 19
[7] => 16
[6] => 14
[5] => 12
[4] => 9
[3] => 7
[2] => 5
[1] => 3
)
[48] => Array
(
[9] => 21
[8] => 19
[7] => 16
[6] => 13
[5] => 11
[4] => 9
[3] => 8
[2] => 5
[1] => 3
)
)
[20] => Array
(
[73] => Array
(
[9] => 20
[8] => 18
[7] => 16
[6] => 13
[5] => 11
[4] => 8
[3] => 6
[2] => 5
[1] => 3
)
[1] => Array
(
[9] => 20
[8] => 17
[7] => 16
[6] => 14
[5] => 12
[4] => 9
[3] => 7
[2] => 4
[1] => 2
)
)
)
In this example, the array shows that players 75 and 48 scored 21 points that player 75 will eventually win on the 6th hole countback (14pts compared to 13pts) and player 48 is 2nd. In the next tied group, players 73 and 1 scored 20 points, and player 73 will win this group on the 8th hole countback and finishes 3rd (18 pts compared to 17 pts), with player 1 in 4th. player 26 is then 5th.
Note, the $tie_loop is added to another array to calculate the 1st to 5th place finishing positions, so that is working.
Hopefully that is enough to help.
Ok, so I don't understand golf at all... hahaha BUT! I think I got the gist of this problem, so heres my solution.
<?php
/**
* Author : Carlos Alaniz
* Email : Carlos.glvn1993#gmail.com
* Porpuse : Stackoverflow example
* Date : Aug/04/2015
**/
$golfers = [
"A" => [1,5,9,1,1,2,3,4,9],
"B" => [2,6,4,2,4,4,1,9,3],
"C" => [3,4,9,8,1,1,5,1,3],
"D" => [1,5,1,1,1,5,4,5,8]
];
//Iterate over scores.
function get_winners(&$golfers, $hole = 9){
$positions = array(); // The score numer is the key!
foreach ($golfers as $golfer=>$score ) { // Get key and value
$score_sub = array_slice($score,0,$hole); // Get the scores subset, first iteration is always all holes
$total_score = (string)array_sum($score_sub); // Get the key
if(!isset($positions[$total_score])){
$positions[$total_score] = array(); // Make array
}
$positions[$total_score][] = $golfer; // Add Golpher to score.
}
ksort($positions, SORT_NUMERIC); // Sort based on key, low -> high
return array(end($positions), key($positions)); // The last shall be first
}
//Recursion is Awsome
function getWinner(&$golfers, $hole = 9){
if ($hole == 0) return;
$winner = get_winners($golfers,$hole); // Get all ties, if any.
if(count($winner[0]) > 1){ // If theirs ties, filter again!
$sub_golfers =
array_intersect_key($golfers,
array_flip($winner[0])); // Only the Worthy Shall Pass.
$winner = getWinner($sub_golfers,$hole - 1); // And again...
}
return $winner; // We got a winner, unless they really tie...
}
echo "<pre>";
print_R(getWinner($golfers));
echo "</pre>";
Ok... Now ill explain my method...
Since we need to know the highest score and it might be ties, it makes no sense to me to maintain all that in separate arrays, instead I just reversed the
golfer => scores
to
Tota_score => golfers
That way when we can sort the array by key and obtain all the golfers with the highest score.
Now total_score is the total sum of a subset of the holes scores array. So... the first time this function runs, it will add all 9 holes, in this case theres 3 golfers that end up with the same score.
Array
(
[0] => Array
(
[0] => A
[1] => B
[2] => C
)
[1] => 35
)
Since the total count of golfers is not 1 and we are still in the 9th hole, we run this again, but this time only against those 3 golfers and the current hole - 1, so we are only adding up to the 8th hole this time.
Array
(
[0] => Array
(
[0] => B
[1] => C
)
[1] => 32
)
We had another tie.... this process will continue until we reach the final hole, or a winner.
Array
(
[0] => Array
(
[0] => C
)
[1] => 31
)
EDIT
<?php
/**
* Author : Carlos Alaniz
* Email : Carlos.glvn1993#gmail.com
* Porpuse : Stackoverflow example
**/
$golfers = [
"77" => [2,4,6,8,10,12,14,16,18],
"79" => [3,5,7,9,11,14,15,17,18],
"76" => [2,4,6,8,10,12,14,16,18],
"78" => [3,5,7,9,11,13,15,17,18]
];
//Iterate over scores.
function get_winners(&$golfers, $hole = 9){
$positions = array(); // The score numer is the key!
foreach ($golfers as $golfer => $score) { // Get key and value
//$score_sub = array_slice($score,0,$hole); // Get the scores subset, first iteration is always all holes
$total_score = (string)$score[$hole-1]; // Get the key
if(!isset($positions[$total_score])){
$positions[$total_score] = array(); // Make array
}
$positions[$total_score][] = $golfer; // Add Golpher to score.
}
ksort($positions, SORT_NUMERIC); // Sort based on key, low -> high
return [
"winner"=> end($positions),
"score" => key($positions),
"tiebreaker_hole" => [
"hole"=>$hole,
"score"=> key($positions)],
]; // The last shall be first
}
//Recursion is Awsome
function getWinner(&$golfers, $hole = 9){
if ($hole == 0) return;
$highest = get_winners($golfers,$hole); // Get all ties, if any.
$winner = $highest;
if(count($winner["winner"]) > 1){ // If theirs ties, filter again!
$sub_golfers =
array_intersect_key($golfers,
array_flip($winner["winner"])); // Only the Worthy Shall Pass.
$winner = getWinner($sub_golfers,$hole - 1); // And again...
}
$winner["score"] = $highest["score"];
return $winner; // We got a winner, unless they really tie...
}
echo "<pre>";
print_R(getWinner($golfers));
echo "</pre>";
Result:
Array
(
[winner] => Array
(
[0] => 79
)
[score] => 18
[tiebreaker_hole] => Array
(
[hole] => 6
[score] => 14
)
)
This question already has answers here:
How can I sort arrays and data in PHP?
(14 answers)
Closed 8 years ago.
Im trying to figure out how to sort the array below so that past array items are sent to the end of the array staying in start_date descending order.
Edit. Id probably include a time array key value item in all arrays to sort by start_date.
[216] => Array (
[title] => Production 1
[start_date] => 20th Feb
[end_date] => 23rd Feb 2015
[ticket_link] => http://www.google.co.uk
[writer] => Sarah Ruhl
[thumb_image] => /files/3514/1762/4350/Biz-Bio-Pic.jpg
[past] => 1
)
[218] => Array(
[title] => Production 3
[start_date] => 27th Feb
[end_date] => 2nd Mar 2015
[ticket_link] => www.google.co.uk
[writer] => Sarah Ruhl
[thumb_image] => /files/9414/1762/4351/Dan-Bio-Pic.jpg
[past] => 1
)
[219] => Array (
[title] => Production 4
[start_date] => 3rd Mar
[end_date] => 5th Mar 2015
[ticket_link] => www.google.co.uk
[writer] => Sarah Ruhl
[thumb_image] => /files/4314/1762/4351/Kate-Bio-Pic.jpg
[past] => 0
)
Try this -
function checkdate($a, $b)
{
$a = strtotime($a['start_date']);
$b = strtotime($b['start_date']);
if ($a == $b) {
return 0;
}
return ($a > $b) ? -1 : 1;
}
function checkpast($a, $b)
{
$a_start = strtotime($a['start_date']);
$b_start = strtotime($b['start_date']);
if ($a_start == b_start ) {
return ($a['past'] > $b['past']) ? -1 : 1;
}
}
$array = //your array
usort($array, "checkdate");
usort($array, "checkpast");
I'm using some api which returns the list of transactions done by the user in XML format. This is how it looks like.
<Response>
<Status>00</Status>
<STMT>
<T0>
<ID>25624</ID>
<DATE>30 JUNE 2014</DATE>
<Amount>1500</Amount>
</T0>
<T1>
<ID>11495</ID>
<DATE>29 JUNE 2014</DATE>
<Amount>1000</Amount>
</T1>
<T2>
----
----
----
</STMT>
<Bal>55</Bal>
</Response>
Now, how do we get those values inside STMT tags? I tried this, but didn't work.
$result=simplexml_load_string($xmlstring);
$i='0';
$tx ='T'.$i;
while ($result->STMT->$tx) {
$result->STMT->$tx->ID;
$tx='T'.strval(intval($i++));
}
Please help.
Actually this is just straightforward. Do something like this:
$xml_string = '<Response><Status>00</Status><STMT> <T0> <ID>25624</ID> <DATE>30 JUNE 2014</DATE> <Amount>1500</Amount> </T0> <T1> <ID>11495</ID> <DATE>29 JUNE 2014</DATE> <Amount>1000</Amount> </T1> <T2> <ID>11496</ID> <DATE>28 JUNE 2014</DATE> <Amount>500</Amount> </T2></STMT><Bal>55</Bal></Response>';
$xml = simplexml_load_string($xml_string);
$stmt = $xml->STMT;
$stmt = json_decode(json_encode($stmt), true);
echo '<pre>';
print_r($stmt);
Output:
Array
(
[T0] => Array
(
[ID] => 25624
[DATE] => 30 JUNE 2014
[Amount] => 1500
)
[T1] => Array
(
[ID] => 11495
[DATE] => 29 JUNE 2014
[Amount] => 1000
)
[T2] => Array
(
[ID] => 11496
[DATE] => 28 JUNE 2014
[Amount] => 500
)
)
It works. You didn't echo the result...
echo $result->STMT->$tx->ID . "\n";
Also, $i++ should be changed to ++$i.