I'm trying to do a sort in my WP_Query on a custom field. The custom field contains strings such as "E100", "E500" and "E123b". I would like to sort numerically on these values, i.e. sort on the custom field as if the characters weren't there.
My query looks like this:
$subpages = new WP_Query(array(
"post_type" => "page",
"meta_key" => "[customFieldNameHere]",
"orderby" => "meta_value_num",
"order" => "ASC",
"posts_per_page" => 5000
));
But it doesn't work. It does some sort of sort, but it's not numerical. Is it possible to strip all characters/letters from the field, and then do a numerical sort on the remaining values, or is there some other way to solve this?
You can't sort a string with letters as if it were all numbers. If you try you will get a alphanumerical sort-- more or less what you'd do if you were alphabetizing something but it makes numbers look odd because it matches up all the first characters, then the second, and so on making numbers look like:
1
10
101
2
20
I don't know of anything built into MySQL that will do what you want, nor does WP_Query have any such feature. The best solution I have is to pull your results unsorted, and sort them later. You want to pull unsorted so the database doesn't do extra work.
$subpages = new WP_Query(array(
"post_type" => "page",
"meta_key" => "[customFieldNameHere]",
"posts_per_page" => 5000
));
$sorted = array();
foreach ($subpages as $s) {
$kname = preg_replace('/[^0-9]+/','',$s->customFieldNameHere]);
$sorted[$kname] = $s;
}
// you may need
// ksort($sorted);
var_dump($sorted);
One problem is going to be collisions. If you end up with two matching $knames you will clobber data, and frankly, that seems pretty likely if you have a lot of data.
I ended up removing the leading E from all strings. Doesn't really solve the original problem, with numerical sorting of strings, but at least it works now.
Related
Ive come upon the following code and having trouble deciphering its use.
(changed up the variable names a bit for simplicity)
$fooo = array(
'dog' => array('pages', 'home'),
'cat' => array('users', 'login'),
'bird' => array('users', 'reset', 1),
);
I am familiar with associative arrays but have not seen this "nested array" implementation before.
Is this code creating an array of arrays?
For example, $fooo['dog'] returns an array where $dog[0]='pages' and $dog[1]='home'
That seems wrong.
Yes, this is an array of arrays. But it perhaps may be more accurate to describe it as an associative array with an indexed array for every value.
The following can be done with it:
$fooo['dog'] // gets array("pages", "home")
$fooo['bird'][0] // gets "users"
$fooo['cat'][1] // gets "login"
$fooo['cow'] = array('x', 'y'); // adds another value to the outer array
$fooo['bird'][] = 2; // $fooo['bird'] now equals array('users', 'reset', 1, 2)
There is nothing wrong with this code, but your example is lacking practicality. There is plenty of code that uses such structures though. For example, a logical representation of a menu with sub-menus on a website (which seems like the source of your sample), this data structure can then be looped to generate an HTML/CSS menu.
I hope the title is descriptive, I am stuck so I am going to do my best to describe the issue.
I have a comparison I need to make for bed types on a search I am building. One is a $_POST array from the search form ($array1). It lists the bed types, so for example it would look something like:
array('King', 'Queen', 'Full');
My second array ($array2) is from my CMS's profile information and looks like this:
array(
"field_bed_types" => array(
"und" => array(
"0" => array(
"value" => "King"
)
"1" => array(
"value" => "Double"
)
)
)
)
The more bed types they have selected in their profile (there are 6) the more entries there would be past "1" in $array2.
What I am trying to achieve it to take the search types from $array1 and see if $array2 has all of the bed types listed in referenced in $array1. If not, I am doing a continue; and moving on to the next user profile record in my foreach loop.
In this example above, given that $array2 has only King and Double and $array1 is looking for a King, Queen and Full bed, the search should come back as FALSE and then continue to the next record. My question is, how do I do this?
I hope this makes sense, please let me know if you have any further questions.
Note: Drupal is the CMS in use here, but for all purposes this is still a multidimensional array, I just mention my CMS as a way to say that I don't have a way to change the data structure.
Try this
foreach($array1 as $key=>$type)
{
$return[$key]=false;
foreach($array2['field_bed_types']['und'] as $typeArray)
{
if ($type==$typeArray['value'])
$return[$key]=true;
}
}
$failed=false;
foreach($return as $match)
{
if($match==flase)
{
$failed=true;
}
}
if($failed==false)
{
// do stuff if passed
}
I added a code that allows me to sort WordPress posts by custom fields. I'm trying to sort the posts by prices, but it's sorting by the first number and not the value:
$116.99
$12.95
$149.00
$15.99
Instead of:
$12.95
$15.99
$116.99
$149.00
How can I get it to sort properly?
Here's the code: http://pastebin.com/Pe5yfvrE
I took it from this discussion, but it was left unresolved there..
http://wordpress.org/support/topic/sort-posts-by-custom-field-in-backend
If you would like to do it manually (though the answers referencing WP_Query are better options), a reasonably nice treatment might use array_multisort:
$arr = array(
'$116.99',
'$12.95',
'$149.00',
'$15.99'
);
$keys = array();
foreach ($arr as $value) {
$keys[] = floatval(substr($value, 1));
}
array_multisort($keys, SORT_ASC, $arr);
Use the WP_Query class and the orderby=meta_value_num parameter to sort numerically. Also, make sure you store the price in the custom field as a number without the "$" prepended.
$query = new WP_Query( array ( 'orderby' => 'meta_value_num', 'meta_key' => 'price' ) );
$query then contains rows of posts sorted numerically by price.
I haven't had a look at your code but you this has to do with the numbers being strings in your case. If you sort a string it is sorted like you describe. In order to sort it by it's value you need to remove the $ sign and cast it to a number.
Did you see this technique? - adding zero to the meta value of the to force it to be treated as an integer. The post has been updated various times over the years too so it might help you;
http://wordpress.org/support/topic/order-by-meta_key-where-meta_value-is-number?replies=11
function order($a, $b) {return intval($b) - intval($a);}
uasort($array, 'order');
I wonder that can help you ;)
I am seeking for someone's knowledge out here.
Right now, I would need to merge several arrays into a bigger one, but all of those arrays depend on a function.
This function returns a numeric array containing different quantities of numbers between 1 and 7 :
function Possible($i, $j, $grid)
$possible = Possible($i, $j, $grid)
I'm working with a grid, and the function returns a different array for every case of the grid. What I would like to do is to merge those 7 arrays into another one. Some numbers may be present more than once in this big array, but I want it this way.
I tried using for loops, while loops and some other techniques, but nothing worked. In this case, it is not possible to manually define every array, since they change depending of what is contained in the grid and there are too many. It has to be done automatically, and this is where I get stuck.
for ($jj=0; $j<7; $j++){
$possRow = array_merge( ###what do I add here or what do I change in this code to make everything work###
Thank you if someone can help me out!
Etpi
hope this help:
$biggerOneArray = array();
for($k=0;$k<7;$k++) {
$biggerOneArray[] = Possible($i,$j,$grid);
}
Then you can check your bigger array, may contains all arrays of the iterations of the loop (7 arrays merged).
var_dump($biggerOneArray);
The output should be this:
array(
(int) 0 => array(
'key' => 'value',
'key2' => 'value2'
),
(int) 1 => array(
'key3' => 'value3',
'key4' => 'value4'
)
)
etc...
I'm sorry but your description isn't very clear. But just to get you started you might look at this solution.
function Possible($i, $j, $grid) {
// some code ... e.g. $array[] = "some data";
return $array;
}
By creating a small array for each grid and returning it using return $array you get a few little arrays which you can inturn place into a for loop to merge it into one larger array. However i believe the var $jj must have some meaning in the function it self as well.
for($jj=0;$jj<7;$jj++) {
$merged_array[$jj] = Possible($i,$j,$grid);
}
Maybe if you descripe your problem a little more and post an exmple of the array's your working with i can give you a better answer.
I'm new to the stackoverflow so feel free to delete this question if it's stupid:
The main purpose of doing this is to display a list of details on a page randomly everytime it refreshes, but the details are in different arrays, so i have 2 arrays which i have to randomize in the same way,
Example:
$Name[0]=John;
$Name[1]=Lucy;
$Name[2]=Mike;
$Age[0]=18;
$Age[1]=20;
$Age[2]=25;
after being randomize becomes :
$Name[2]=Mike;
$Name[0]=John;
$Name[1]=Lucy;
$Age[2]=25;
$Age[0]=18;
$Age[1]=20;
I tried using "->", For example:
$Array[0]->name = 'John';
$Array[0]->age = '18';
$Array[1]->name = 'Lucy';
$Array[1]->age = '20';
shuffle($Array);
but my teacher wasn't thrilled because the code was messy since there's alot of transfer (Details into the new array before the randomizing and new array back into details after randomizing). He wants me to do it only with the 2 arrays.
What you are doing, is sort of the right way of doing things. Look at it this way. What exactly are you trying to achieve? You want a set of data sorted randomly (ok, sorting is not the right word here, but you get it). Whenever you talk about any kind of reordering of data, we talk about changing the order that the elements appear in. Your element here is neither 'name', nor 'age'. Your element here is 'person'. So, your data list should be a list of 'person's, which you would reorder and not in two loosely-coupled arrays.
Anyways, if you absolutely MUST do it this way. This is what I suggest.
Let there be two arrays $A and $B. Let them both have N elements. What you do is, create an array $nums, which has elements from 0 to N-1 i.e.
$nums = array(0, 1, 2 ... N-1)
Now, shuffle the $sums array. So, let's say we have something like:
$num = (3, 4, 1, 2)
Ok, so we have created a mapping here,
$num[0] = 3
means that the 0th element is 3, which you can interpret as in the new array, the 0th element should be the 3rd element of the old array. To do this, run a simple loop:
for($i=0; $i<N; $i++) {
$A2[$i] = $A[$num[$i]];
$B2[$i] = $B[$num[$i]];
}
It is a slightly challenging task if you insist on this being an online solution (a solution that modifies the original data structure and not build a new one), but I'll leave that ask to you (think of swapping data elements according to the map we just created). Also, you could extend it easily to more than 2 arrays, or an array of arrays in case you're not sure how many arrays one has to deal with. Feel free to ask any question you might have...
You should use an associative array.
$people = array('John' => 18, 'Lucy' => 20, 'Mike' => 25);
return shuffle_assoc($people);
function shuffle_assoc( $array )
{
$keys = array_keys( $array );
shuffle( $keys );
return array_merge( array_flip( $keys ) , $array );
}