Sorting multidimensional arrays in PHP? - php

I'm having some troubles sorting events for my website in wordpress.
I'm using custom fields to create events with a title, a description and a date.
I put every events date in an array:
$datesEvenements = array();
array_push($datesEvenements,get_field('date'));
I then get the timestamp for each date:
foreach($datesEvenements as $value){
$timestamp = strtotime($value);
array_push($tsEvenements,$timestamp);
}
I then proceed to sort my timestamp by replacing the past event by 0 or an association of the event timestamp with the difference between that timestamp and the present one.
$arrEventDelta = array();
for($i=0;$i<count($tsEvenements);$i++){
$tsi = $tsEvenements[$i];
if($ts>$tsi){
array_push($arrEventDelta,0);
}
elseif($ts<=$tsi){
array_push($arrEventDelta,array('TimestampEvenements'=>$tsi,'DeltaEvenements'=>$deltaTs));
}
After that, I would like to order the array '$arrEventDelta' by the 'DeltaEvenements' value.
Unfortunately, I'm a bit confused with all those arrays. I've tried the array_multisort function like so:
$DeltaEvents = array();
foreach($arrEventDelta as $key => $row){
$DeltaEvents[$key] = $row['DeltaEvents'];
}
array_multisort($DeltaEvents, SORT_ASC, $arrEventDelta);
But it doesn't work. Any tips on how I could fix this?
This is what is outputed from this,
Array ( [0] => 0 [1] => Array ( [TimestampEvenements] => 1394582400 [DeltaEvenements] => **31923** ) [2] => Array ( [TimestampEvenements] => 1394668800 [DeltaEvenements] => **118323** ) [3] => 0 [4] => 0 )
I need to order the highlighted numbers in increasing order.

Related

How can I restructure this array to condense the data into a more usable format in PHP?

I will try to explain the data I'm working with first, then I'll explain what I hope to do with the data, then I'll explain what I've tried so far. Hopefully someone can point me in the right direction.
What I'm working with:
I have an array containing survey responses. The first two items are the two answers for the first question and responses contains the number of people who selected those answers. The last three items are the three answers for the other question we asked.
Array
(
[0] => Array
(
[survey_id] => 123456789
[question_text] => Have you made any changes in how you use our product this year?
[d_answer_text] => No
[responses] => 92
)
[1] => Array
(
[survey_id] => 123456789
[question_text] => Have you made any changes in how you use our product this year?
[answer_text] => Yes
[responses] => 30
)
[2] => Array
(
[survey_id] => 123456789
[question_text] => How would you describe your interaction with our staff compared to prior years?
[answer_text] => Less Positive
[responses] => 14
)
[3] => Array
(
[survey_id] => 123456789
[question_text] => How would you describe your interaction with our staff compared to prior years?
[answer_text] => More Positive
[responses] => 35
)
[4] => Array
(
[survey_id] => 123456789
[question_text] => How would you describe your interaction with our staff compared to prior years?
[answer_text] => No Change
[responses] => 72
)
)
What I want to achieve:
I want to create an array where the question_text is used as the key (or I might grab the question_id and use it instead), use the answer_text as a key, with the responses as the value. It would look something like this:
Array
(
[Have you made any changes in how you use our product this year?] => Array
(
[No] => 92
[Yes] => 30
)
[How would you describe your interaction with our staff compared to prior years?] => Array
(
[Less Positive] => 14
[More Positive] => 35
[No Change] => 72
)
)
Here's what I've tried:
$response_array = array();
foreach($result_array as $value){
//$responses_array['Our question'] = array('answer 1'=>responses,'answer 2'=>responses);
$responses_array[$value['question_text']] = array($value['answer_text']=>$value['responses']);
}
This does not work because each loop will overwrite the value for $responses_array[$question]. This makes sense to me and I understand why it won't work.
My next thought was to try using array_merge().
$responses_array = array();
foreach($result as $value){
$question_text = $value['question_text'];
$answer_text = $value['answer_text'];
$responses = $value['responses'];
$responses_array[$question_text] = array_merge(array($responses_array[$question_text],$answer_text=>$responses));
}
I guess my logic was wrong because it looks like the array is nesting too much.
Array
(
[Have you made any changes in how you use our product this year?] => Array
(
[0] => Array
(
[0] =>
[No] => 92
)
[Yes] => 30
)
My problem with array_merge is that I don't have access to all answers for the question in each iteration of the foreach loop.
I want to design this in a way that allows it to scale up if we introduce more questions with different numbers of answers. How can this be solved?
Sounds like a reduce job
$response_array = array_reduce($result_array, function($carry, $item) {
$carry[$item['question_text']][$item['answer_text']] = $item['responses'];
return $carry;
}, []);
Demo ~ https://eval.in/687264
Update
Remove condition (see #Phil comment)
I think you are looking for something like that :
$output = [];
for($i = 0; $i < count($array); $i++) {
$output[$array[$i]['question_text']] [$array[$i]['answer_text']]= $array[$i]['responses'];
}
print_r($output);
Slightly different approach than the answer posted, more in tune with what you'v already tried. Try This:
$responses_array = array();
$sub_array = array();
$index = $result[0]['question_text'];
foreach($result as $value){
$question_text = $value['question_text'];
$answer_text = $value['answer_text'];
$responses = $value['responses'];
if (strcmp($index, $question_text) == 0) {
$sub_array[$answer_text] = $responses;
} else {
$index = $question_text;
$responses_array[$index] = $sub_array;
$sub_array = array();
}
}
Edit: Found my mistake, updated my answer slightly, hopefully this will work.
Edit 2: Working with example here: https://eval.in/687275

Pull out values from multidimensional associative array

I have a multidimensional array which Im trying to pull all the values of a certain key and assign it to a variable.
This is the array:
Array
(
[I_would_not_know_the_name_of_this_key] => Array
(
[interval] => 3600
[display] => Once Hourly
)
[nor_this_one] => Array
(
[interval] => 43200
[display] => Twice Daily
)
[nor_this_one] => Array
(
[interval] => 86400
[display] => Once Daily
)
)
I want to always get the [display] value even when I do not know what the upper level value is.
function which contains the array above, more schedules can be added which is why I said I would not always know the top level key: https://codex.wordpress.org/Function_Reference/wp_get_schedules
My code so far:
$active_cron_schedules = wp_get_schedules(); //this is the
foreach ($active_cron_schedules as $key => $value) {
echo $key;
}
?>
This outputs for example: 'I_would_not_know_the_name_of_this_key', 'nor_this_one', 'nor_this_one', I need to get in deeper.
Arrays have always given me a run for my money in PHP can't figure out how to loop through it :(
Thank you
I think what you are trying to do will be solved with a foreach() loop or array_column() depending on your version of php. The variable part is hard to answer because you have not given an example of what you would be doing with the variable. A common mistake is to overwrite the variable in a loop, but if all you want are all the display values (or any other key), try:
function getValByKey($array, $getKey = 'display')
{
$new = array();
foreach($array as $arr) {
if(empty($arr[$getKey]))
continue;
$new[] = $arr[$getKey];
}
return $new;
}
$result = array(
'key1'=> array('interval'=>1,'display'=>'1d'),
'key2'=> array('interval'=>2,'display'=>'2d'),
'key3'=> array('interval'=>3,'display'=>'3d')
);
// To use
$display = getValByKey($result);
print_r($display);
// Array column has the same basic function, but
// Only available in PHP 5 >= 5.5.0, PHP 7
$display = array_column($result,'display');
print_r($display);
Both give you:
Array
(
[0] => 1d
[1] => 2d
[2] => 3d
)
whatever is the key, you dont even need to know it in a foreach.
here is a sample. $key can be anything. you just have to check for it s interval child element.
$interval_list = array();
foreach ($array as $key => $el) {
if (isset($el['interval'])) {
$interval_list[] = $el['interval'];
}
}

Query 2 dimensional array using native php array functions

I have converted a CSV to a two dimensional array where the following array structure stores the column and row data
$table['status'] = ['active', 'active', 'inactive'];
$table['plan'] = ['annual', 'weekly', 'weekly '];
$table['spend'] = ['12,000', '19,000', '0' ];
print_r($table);
would appear as follows:
( [status] => Array ( [0] => active [1] => active [2] => inactive )
[plan] => Array ( [0] => annual [1] => weekly [2] => weekly )
[spend] => Array ( [0] => 12,000 [1] => 19,000 [2] => 0 ) )
I want to use native PHP array functions to query the arrays without having to write loops with nested conditions. If this was a MySQL database and I wanted to find the sum of spend from accounts with active status and weekly plans I would simply run the following query
SELECT SUM('Spend') FROM table WHERE status = 'Active' AND plan = 'Weekly';
But instead I have to take the following approach using a for loop
for ($index = 1; $index < count($table); $index++){
if (($table['status'][$index] == 'active') && ($table['plan'][$index] == 'weekly')){
$spend[$index] = $table['spend'][$index];
}
}
echo array_sum($spend);
This approach gives me a headache. Is there an obvious solution for refactoring this into php's native array functions or is a mess of explicit loops inevitable?
There aren't any native functions to do what you want. What's wrong with storing the information from the CSV files into a database?
If that's simply not an option then try foreach loops, they're much cleaner.
$spend = array();
foreach ($table['spend'] as $key => $amount)
{
if ($table['status'][$key] == 'active' && $table['plan'][$key] == 'weekly')
{
$spend[] = $amount;
}
}
Whilst it doesn't solve the loops issue it does help clean them up so you don't lose your mind so much.
Using Array Keys to get all "active" keys, then loop through only those to find the matches.
$keys = array_keys($table['status'], 'active');
foreach($keys as $key)
{
if($table['plan'][$key] == 'weekly')
{
$spend[] = $table['spend'][$key];
}
}
print_r($spend);
Spend:
Array
(
[0] => 19,000
)
this is pretty messy but I found one way of doing it
$keys = array_intersect(array_keys($table['status'], 'active'), array_keys($table['plan'], 'weekly'));
$subs['total'] = array_intersect_key($table['spend'], array_flip($keys));
print_r(array_sum($subs['total']));

PHP: Plot Data Points From MySQL on Graph (Google Graphs)

I'm trying to query our database to get all records that match the user defined query, and store the data in a formatted array. The problem is, I'm getting all of the records, but not really sure how to process the data appropriately. I've been working on this for a few days now and haven't made much head way after trying a variety of ideas. Hopefully, someone here will have some insight to share.
The code below executes the query and starts processing the returned data into the array:
$msg_vol = array();
$xy_coords = array();
$tweet_count = 1;
$query = "SELECT created_at, tweet_id FROM `tweets` WHERE tweet_text LIKE '%{$safe_q}%' AND created_at < now() - 300";
$tweets = mysqli_query($db, $query);
confirm_query($tweets);
while ($tweet = mysqli_fetch_assoc($tweets)) {
$created_at = $tweet['created_at'];
$timestamp = strtotime($created_at);
$created_at_no_seconds = date('Y-m-d H:i', $timestamp);
if(!in_array($created_at_no_seconds, $xy_coords)) {
$created_at = $tweet['created_at'];
$timestamp = strtotime($created_at);
$created_at_no_seconds = date('Y-m-d H:i', $timestamp);
if(!in_array($created_at_no_seconds, $xy_coords)) {
$xy_coords = array(0 => $created_at_no_seconds, array('tweet_count' => $tweet_count, 'retweets' => 0));
} else {
// $created_at_no_seconds exists in array
// update array
$msg_vol[$created_at_no_seconds] = array('tweet_count' => $tweet_count++, 'retweets' => 0);
}
}
return $msg_vol;
I'm reformatting the $created_at to the minute as, for the time being, I'm only interested in the data for the last 5 minutes (300 seconds) and want each minute separated out into it's own associative array. The $created_at_no_seconds variable can potentially contain duplicate entries to be added in the array. So, I've toyed with in_array() to try and check if it exists and only add it to the array if it does not. I didn't have much luck with this yet.
A print_r($msg_vol) provides the following output (which is slowly getting closer to the desired output):
[0] => Array
(
[created_at] => 2013-12-15 19:09
[tweet_count] => 1
[retweets] => 0
)
[2013-12-15 19:09] => Array
(
[tweet_count] => 11
[retweets] => 0
)
[1] => Array
(
[created_at] => 2013-12-15 19:09
[tweet_count] => 1
[retweets] => 0
...
[12] => Array
(
[created_at] => 2013-12-15 19:10
[0] => Array
(
[tweet_count] => 12
[retweets] => 0
)
)
[2013-12-15 19:10] => Array
(
[tweet_count] => 20
[retweets] => 0
)
[13] => Array
(
[created_at] => 2013-12-15 19:10
[0] => Array
(
[tweet_count] => 12
[retweets] => 0
)
)
...
(I'm not processing the retweets at the moment, so I'm simply adding a 0 to the retweets array as a placeholder).
I'm trying to format it so that in one array, it contains the unique date (down to the minute) where the values for tweet_count is stored within it. The above example with the date as the associative key, and the $k => $v inside is what I'm trying to achieve. But, when I keep getting the array populated with [0], [1]. [12], [13], etc.
Am I even close? This has been quite the rabbit hole... And, it's starting to become a dark and lonely place. :(
instead of using array push like this
array_push($msg_vol, $xy_coords);
why not try
$array[] = $xy_coords;
With regards the duplicates why not use SELECT DISTINCT in your mysql query?
I was able to solve the problem by optimizing the query (Thank you #php)!
$query = "SELECT DATE_FORMAT(created_at, '%Y-%d-%m %H:%i'),";
$query .= " COUNT(tweet_id), 0 FROM `tweets`";
$query .= " WHERE tweet_text LIKE '%{$safe_q}%'" ;
$query .= " AND created_at < now() - 300";
$query .= " GROUP BY DATE_FORMAT(created_at, '%Y-%d-%m %H:%i')";
$tweets = mysqli_query($db, $query);
confirm_query($tweets);
while ($tweet = mysqli_fetch_assoc($tweets)) {
echo '<pre>';
print_r($tweet); exit;
echo '</pre>';
}
Make use of MySQL functions. They are a life (and, hair) saver!

If value exists in one PHP array, add value to second array

I have two PHP arrays. One contains a group name and another contains a pay wage value.
$group_wages_array = Array ( [0] => 1 [1] => 4 [2] => 1 [3] => 3 );
This means there are four employees on the schedule. Two are assigned to group 1, another to group 4 and the last to group 3.
The second array is as follows:
$tot_wages_array = Array ( [0] => 500 [1] => 44 [2] => 80 [3] => 11.25 );
This is a sample array of each employee's wage. Both arrays are constructed in order as values are added in a mysql while loop as it pulls the info from the database.
Later on down the line, I combine the two arrays to get one array where the key is the group number and the value is the total wages for that group:
$combined_group_wages = array_combine($group_wages_array, $tot_wages_array);
This works like a charm EXCEPT for when more than one employee is assigned to the same group. These arrays are built in a mysql while loop as it loops through each employee's info:
array_push($tot_wages_array, $totemp_wages_sch); // Add their wage to the array
array_push($group_wages_array, $emp_data['group_id']); // Add their group to the array
Instead of just pushing the data to the array, I need to do this... I know the english but I don't know how to code it:
If $emp_data['group_id'] exists as value in $group_wages_array, add nothing to this array but get the key. Add $totemp_wages_sch to $tot_wages_array where key = group_wages_array key
I know it sounds more like an SQL query but I have to keep the keys and values in order so that they can be combined later in the page. If I can get this to work right, The arrays shown in the example would be:
$group_wages_array = Array ( [0] => 1 [1] => 4 [2] => 3 );
$tot_wages_array = Array ( [0] => 580 [1] => 44 [2] => 11.25 );
$combined_group_wages = array_combine($group_wages_array, $tot_wages_array);
$combined_group_wages = Array ( [1] => 580 [4] => 44 [3] => 11.25 );
...I've got to make this work using PHP. Any ideas?
I came up with a solution based on a combination of two of the answers submitted below. Here it is if it can help someone:
if(in_array($emp_data['group_id'], $group_wages_array)){
$key = key($group_wages_array);
$tot_wages_array[$key] += $totemp_wages_sch;
} else {
array_push($group_wages_array, $emp_data['group_id']);
array_push($tot_wages_array, $totemp_wages_sch);
}
This should do it:
$group_wages_array = array(1, 4, 1, 3);
$tot_wages_array = array(500, 44, 80, 11.25);
$combined_group_wages = array();
for ($i=0; $i<count($group_wages_array); $i++) {
$group = $group_wages_array[$i];
if (array_key_exists($group_wages_array[$group], $combined_group_wages)) {
$combined_group_wages[$group] += $tot_wages_array[$i];
} else {
$combined_group_wages[$group] = $tot_wages_array[$i];
}
}
print_r($combined_group_wages);
Yields:
Array
(
[1] => 580
[4] => 44
[3] => 11.25
)
But I recommend that you just switch to using objects to better represent your data.
If I could see the entirety of the code that would help a lot, but here's your English converted to php. Show me more code and I can perfect it, until then try this ->
if(in_array($emp_data['group_id'], $group_wages_array)){
$key = key($group_wages_array);
$tot_wages_array[$key] = $totemp_wages_sch;
} else {
array_push($group_wages_array, $emp_data['group_id']);
}

Categories