Here is an extract of my test code and data:-
//Update Array
$civs[1][1]="1";
$civs[1][2]="Inca";
$civs[2][1]="2";
$civs[2][2]="India";
//Sort Array
array_multisort($civs[0][2], SORT_DESC, SORT_STRING,
$civs[0][1], SORT_NUMERIC, SORT_DESC);
Output:-
Warning: array_multisort(): Argument #1 is expected to be an array or
a sort flag in ~/test.php on line 3
array(3) { [1]=> array(2) { [1]=> string(1) "1" [2]=> string(4) "Inca" } [2]=> array(2) { [1]=> string(1) "2" [2]=> string(5) "India" } [0]=> array(2) { [2]=> NULL [1]=> NULL } }
Problem statement
Depending on what the User selects I need to sort the array in PHP either on the 1st (numeric) or 2nd (alphanumeric) element of the 2nd part of the array but can't see how to do that, the various PHP sorts don't seem to allow you to tell it what is to be sorted on, have tried the above code . The PHP Manual for uksort says "If the array you wish to sort needs to be sorted by some non-trivial criteria," well numeric is about as trivial as it gets!
I've been looking at this for a couple of hours now and am sure I must be missing something as all I can see is that I have to write a custom function but surely PHP knows how to do simple sorts based on numeric or text values?
Main question I found was this:- How can I sort arrays and data in PHP? and I also spent a fair bit of time browsing through http://php.net/manual/en/array.sorting.php.
Apologies if I have missed something obvious.
Related
I have a PHP array, that I want to pass over to jQuery and update the rows on the page.
This PHP array is the 'name' of the checkboxes selected on the page. (So this array can be of any length, depending on what the user selects)
PHP Array:
var_dump($sr->conflict_return);
OUTPUT CHECK: array(5) { [0]=> string(33) "hours_9_7_reg_session_102_905_925" [1]=> string(33) "hours_9_7_reg_session_101_905_925" [2]=> string(33) "hours_9_7_reg_session_103_905_925" [4]=> string(33) "hours_9_7_reg_session_104_845_915" [13]=> string(33) "hours_9_7_reg_session_103_845_905" }
This this case... there are '5' elements in my [php] array.
Here is where my problem comes into play...
Sometimes it 'works'... sometimes it doesnt..
The 'key' seems to be what is IN the array:
OUTPUT CHECK: array(3) { [0]=> string(33) "hours_9_7_reg_session_102_845_905" [1]=> string(33) "hours_9_7_reg_session_101_845_905" [2]=> string(33) "hours_9_7_reg_session_104_845_915" }
this seems to work.. 3 items in array.. all 3 rows on stage get highlighted.
this:
OUTPUT CHECK: array(4) { [0]=> string(33) "hours_9_7_reg_session_102_845_905" [1]=> string(33) "hours_9_7_reg_session_101_845_905" [2]=> string(33) "hours_9_7_reg_session_103_845_905" [4]=> string(33) "hours_9_7_reg_session_104_845_915" }
doesnt work... and none of the rows are highlighted
(seems like if there is 4 items in the array it breaks??)
my jQuery to parse the data:
var conflictItems = <?=json_encode($sr->conflict_return); ?>;
//has a conflict list
if(conflictItems.length > 0){
alert("Has conflicts");
//loop through and highlight elements on stage
for(i=0; i<conflictItems.length; i++){
console.log(conflictItems[i]);
$("#sr_table_"+conflictItems[i]+"_row").addClass("conflict_border");
}
}
When I trace (console.log()) the data.... I get odd results.
console.log('CONFLICT ITEMS: ' + conflictItems);
console.log('CONFLICT COUNT: ' + conflictItems.length);
3 x items in array... the above shows:
CONFLICT ITEMS: hours_9_7_reg_session_103_845_905,hours_9_7_reg_session_102_845_905,hours_9_7_reg_session_104_845_915
CONFLICT COUNT: 3
which to me is correct. I have 3 items in my array passed over from PHP..jQuery runs through list and adds a class to each 'row'.
however, when I add a 4th item... the traced output is:
CONFLICT ITEMS: [object Object]
CONFLICT COUNT: undefined
So how? is my array turning into an object?.. and more so WHY??
and how can I fix this? I dont understand why having 3 items in the array works.. but not 4?
Javascript doesn't have a concept of non-sequential array keys (your example has keys 0,1,2 and 4), thus when running json_encode on the array, it converts it to JSON notation for a JS object.
As #Kenney says in the comments, a possible solution is to keep using arrays, but make use of array_values() function which takes your array, and basically regenerates the array dropping the existing keys and using sequential ones.
You're missing index 3 from your array, therefore js turns it into an object.
This question already has answers here:
How can I sort arrays and data in PHP?
(14 answers)
Closed 7 years ago.
I know similar questions to this have been asked, but even looking at all of them, I can't seem to get this to work. I think it's just a tad bit more complex than the other examples I'm finding. I know someone is going to say it's a repeat question - but I've tried really hard to get it from the examples I've seen so far - so sorry in advance!
So given this multidimensional array $results_display in PHP (var_dump below), there are 5 members of the sub-array "#results", and I want to sort (descending) those 5 by the value in the "#changed" string.
Can someone please help a girl out who's been banging her head against her desk for a couple days?
Thank you so much!!!
What I tried is below the var_dump. I commented out the part with the title to try and get just the first part working.
$results_display =
array(8) {
["#theme"]=> string(18) "hs_filters_results"
["#title"]=> string(18) "On-Demand Webinars"
["#body"]=> NULL
["#results"]=> array(5) {
[0]=> array(3) {
["#changed"]=> string(10) "1403279484"
["#theme"]=> string(17) "hs_filters_result"
["#result"]=> array(25) {
["#nid"]=> string(4) "2057"
["#node_type"]=> array(2) {
["machine_name"]=> string(7) "webinar"
["name"]=> string(7) "Webinar" }
["#title"]=> string(61) "7 Critical Reasons to Automate Handling of IBM i Spool Files "
["#brand_nid"]=> string(2) "29"
["#brand_machine_name"]=> string(5) "brand"
... }
}
...
}
// Obtain a list of columns for the results array
foreach ($results_display as $key => $row) {
$changed[$key] = $row['changed'];
//$title[$key] = $row['title'];
}
// Sort the data with date changed descending, title ascending
// Add $results_display as the last parameter, to sort by the common key
//array_multisort($changed, SORT_DESC, $title, SORT_ASC, $results_display);
array_multisort($changed, SORT_DESC, $results_display);
usort($results_display['results'], function ($a, $b) {
return $a['changed'] - $b['changed'];
});
This should get you started. For more possible sorting options, see https://stackoverflow.com/a/17364128/476.
How can I convert the below array to look like the one right below. I am trying to use array_map but i am confused on how to write the function.
array(3) {
["award_year"]=>
array(2) {
[0]=>
string(7) "1999-01"
[1]=>
string(7) "2010-02"
}
["award_title_user"]=>
array(2) {
[0]=>
string(1) "2"
[1]=>
string(2) "tt"
}
["award_description_user"]=>
array(2) {
[0]=>
string(1) "2"
[1]=>
string(3) "ddd"
}
}
This what i am trying to achieve:
array(2) {
[0]=>
array(3) {
["award_year"]=>
string(7) "2010-02"
["award_title_user"]=>
string(2) "tt"
["award_description_user"]=>
string(3) "ddd"
}
[1]=>
array(3) {
["award_year"]=>
string(7) "1999-01"
["award_title_user"]=>
string(1) "2"
["award_description_user"]=>
string(1) "2"
}
}
$newArr = [];
foreach($oldArr as $key=>$row) {
foreach($row as $index=>$item) {
$newArr[$index][$key] = $item;
}
}
this will solve it, but no checks if data is valid as you mentioned
First things first, #tzook-bar-noy's answer is a better answer in this case, and I am not even advocating the approach I am going to detail here.
When dealing with arrays, I always try to avoid generic loops (ie: foreach()) if I can, instead using the more functional-programming approach that you mention in your question: using functions like array_map(). However the functional-programming functions are very focused in what they do (which is their benefit: they make your code Cleaner), so to use them: you kinda gotta be wanting to do the specific operation they offer.
array_map() has a drawback for your purposes here, in that the mapped array has the same keys in the same order as the original array, which is not what you want here. You need to both turn your original array "inside out", but the ordering of the resultant array you want is the reverse of the original data. Not a good fit for array_map().
It's doable with array_map(), but it's like using a flathead screwdriver when you really need a Philips.
Here's an example:
<?php
$awards = [
"award_year" => ["1999-01", "2010-12"],
"award_title_user" => ["2", "tt"],
"award_description_user" => ["2", "ddd"]
];
$remappedAwards = array_map(function($year, $title, $description){
return [
"award_year" => $year,
"award_title_user" => $title,
"award_description_user" => $description
];
}, $awards["award_year"], $awards["award_title_user"], $awards["award_description_user"]);
$remappedAwards = array_reverse($remappedAwards);
echo "<pre>";
var_dump($remappedAwards);
echo "</pre>";
Obviously I've hardcoded the key names in here too which is less than ideal. One could contrive a generic approach, but by then we'd be so far beyond the actual intent of aaray_map() that the code complexity would be getting daft.
In other languages wherein these array-iteration functions are a bit better implemented (say JS or CFML) one might be able to come up with a half-decent answer with a .reduce() (JS, CFML) kind of operation. However PHP's array_reduce() (and its other array-iteration methods) are hamstrung by their poor implementation as they only pass the value to the callback. They really need to pass at least the index as well, and (less-often-useful, but handy sometimes ~) the array itself as additional arguments to make them anything more than a proof-of-concept. IMO, obviously (I'm biased, I do more JS & CFML than I do PHP, so my expectations are set higher).
Bottom line: array_map() was not a good fit for your requirement here, but I applaud your efforts for thinking to us it as the function-programming approach to array manipulation is definitely a better approach than generic looping where the requirement matches the functionality.
I have a nested array of arrays, and I want to shuffle the inner arrays. My code looks like this (simplified):
$a = array(array('banana', 'peach'), array('ding', 'dong'), array('oh snow'));
foreach ($a as &$arr) {
shuffle($arr);
}
var_dump($a);
The var_dump outputs this:
array(3) { [0]=> array(2) { [0]=> string(5) "peach" [1]=> string(6) "banana" } [1]=> array(2) { [0]=> string(4) "ding" [1]=> string(4) "dong" } [2]=> &array(1) { [0]=> string(7) "oh snow" } }
As you can see in the output, the first two subarrays work, but the third subarray is linked by reference in the output...
In my full app, this last array-link causes problems, but rather than working around the issue, I want to fix this shuffle thing...
Cheers!
This has to do with how PHP stores references to array elements. It cannot reference an element of an array, only values. Therefore it has to store the value array('oh snow') in a "slot" of the symbol table, then make $arr and $a[2] a reference to that value.
To fix this, unset($arr) after the loop. That way only a single variable is referencing the value, which will then be made a regular array index again. Unsetting references after a foreach is good practice anyway, since there are many such gotchas.
I'm trying to make advanced search filters in an application that holds resources (people). I've got all the results in 1 multidimensional array. A user of the application can search for the persons Job title, skills, work field and country.
I've already made the part where I look up the people that meet the criteria given by the user. These results are stored in a multidimensional array. If the user is looking for someone with a specific resource with a job title and a specific skill the return value is this:
$realfilters = array(2) {
["resourcesWithJobtitle"]=> array(6) {
[0]=> string(1) "1"
[1]=> string(2) "48"
[2]=> string(2) "88"
}
["resourcesWithSkill"]=> array(9) {
[0]=> string(1) "4"
[1]=> string(1) "8"
[2]=> string(1) "48"
[3]=> string(2) "50"
}
When the user also looks for a work field this is added to the result:
["resourcesWithWorkfield"]=> array(3) {
[0]=> string(2) "48"
[1]=> string(2) "96"
[2]=> string(2) "97"
}
I need to know which resources meet all dimensions of the array so I can display them. (So in this example I need an array with just 1 value: 48). I think I need to use array_intersect but can't seem to get it right.
One of the possible solutions: you may first extract() the $realfilters array values to variables, and then apply the array_intersect() to them. But this solution is applicable only if there are not many possible filters.
Another one and probably the best solution would be to intersect in a loop, something like:
$res_arr = array_shift($realfilters);
foreach($realfilters as $filter){
$res_arr = array_intersect($res_arr, $filter);
}
$intersection = call_user_func_array('array_intersect', $array);
That will give you the elements present in all the sub arrays of $array.
edit-
This above is like a shortcut for writing:
$intersection = array_intersect($array['a'], $array['b'], ...and so on for all elements...);
A loop could be used as well
$intersection = reset($array);
foreach ($array as $subarr) {
$intersection = array_intersect($intersection, $subarr);
}
print_r($intersection);