I am sorting through an array using the usort function. The loop is working correctly as is the sorting (to some degree) however I seem to have missed something with regards to decimal places etc. My function is below
usort($this->view->blogs, 'comparison');
And here is the function. The function call works correctly and I can see I am returned sorted data
function comparison($a, $b)
{
return strcmp($a->cost_per_blog, $b->cost_per_blog);
}
The issue is with the actual sorting logic for instance I am returned a list like below
0.09724
0.58344
1.16688
12.05776
120.5776
126.60648
13.22464
132.63536
138.66424
168.80864
18.08664
18.08664
18.67008
180.8664
19.25352
21.10108
22.26796
the pattern continues... It appears that I am not taking into account the sorting of 3 digit numbers. I cant seem to think of what I am missing. Any help would be greatly appreciated.
Don't compare strings then, compare numbers:
return $a->cost_per_blog - $b->cost_per_blog;
You compare them as strings not as doubles.
Related
I have this code to check some input data to be sure it fits a proper format. However input_28 is a list field that is sent as an array. Is there a shortcut to check each item in the array for the filter instead of looping through each item?
I dont care what it wrong or which line does not match. I just need to know if any line does not match the filter so I can return the form with an error.
if($_POST['input_28'] != filter_var($_POST['input_28'], FILTER_VALIDATE_REGEXP,array("options"=>array("regexp"=> "/(\d\d\d\d-\d\d\d\d)|()/" )))){
If I understand correctly, you are looking for array_search(), you can use it like this
if(array_search($value, $array)){
// Do stuff
}
Note that array_search() only works if the array is NOT multi-dimensional, you can take a look on the documentation for more references and examples
Some searching on functions that #Alfonso mentioned in his answer led me to another function: preg_grep That led to this little function which worked great.
$input_28=preg_grep("/^(\d\d\d\d-\d\d\d\d)$/", $_POST['input_28'], PREG_GREP_INVERT);
if(count($input_28) > 0){
#Do Something
}
The PREG_GREP_INVERT makes it return an array of entries that do NOT match the filter. Then we count the array, if any did not match the array will have an entry. Thus greater than 0
Instead of working with mysql data, I have created csv file that I plan to use as the source of data for content, etc.
And I have successfully been able to parse the csv and store it into a complex array, that has the following header row aka the keys for the arrays.
"Title","Year","Rated","Released","Runtime","Genre","Director","Writer","Actors","Plot","Language","Country","Awards","Poster","Metascore","imdbRating","imdbVotes","imdbID","Type","Response"
My current stage is to allow dynamic ajax sorting of the arrays.
I have two fields, that I am allowing sorting at the beginning, "Year" and "Title".
So I pass different url paramters, such as "yearasc" or "yeardesc" or "titleasc" or "titledesc".
Then try to sort for that.
So what I did reading a different so post, was to do this.
First I create new arrays that only store the key fields, I need for sorting.
Then based on what sort type, do a different array_multisort.
array_multisort($year, SORT_ASC, $all_rows);
But what I get is results that multiple dupplicate data.
But I wonder if having the first row, be the header row, which is required by the function I pass the data after any sorting to, is causing issues with array sorting.
For simple array sorting, existing functions makes sense and work fine.
But for complicated ones, it is just complex to even understand how to approach solving this problem.
Any suggestions, thoughts or ideas are appreciated and thanked.
Thank you!
I don't have the actual code that is probably going to help you, but I do have a suggestion as for how you can tackle this and make it work..
Keep it simple. First, create your own CSV with just 1 header (Year or Title ) that you want to sort on.
Write your code to sort on that.
Then, add the other one ( Title if you used Year before, or Year if you used Title before ) and sort on whichever you want.
Then, add one more header (say, Rated) that you don't want to sort on.
You should then be able to work with the original CSV.
I'd try to write simple methods and keep your processing to a minimum in each one.
I hope that helps. I realize its more philosophical of an answer, so it is hit or miss if it helps you get the job done. Just realize that this approach will, indeed, take a little more time to write - but the point behind it is that you're taking out all of the "noise" that's getting in your way first. It helps you look at only your problem first and solve that.
You can set a custom sort function to the array. Use asort() if you need to keep original array keys.
<?php
$sortfields = array('year', 'bleh');
function cmp($a, $b) {
global $sortfields;
foreach ($sortfields as $sortfield) {
$cmp = strcmp($a[$sortfield], $b[$sortfield]);
// if desc, invert sign of $cmp
if ($cmp !== 0)
return $cmp;
}
return 0;
}
usort($all_rows, "cmp");
The function usort() calls a user defined comparison function, which returns the same logic from strcmp function: 0 if equal, < 0 is $a is less than $b and > 0 if $a is greater than $b.
This function will compare each field set in $sortfields variable, if it find any comparison that is different (in the order set), it will immediately return the difference.
I have an array called $itemArray[] that contains a set of strings, such as:
myItem_1,
myItem_2,
myItem_3,
myItem_4,
anotherName_1,
anotherName_2,
anotherName_3,
anotherName_4
I also have the following code that goes through the array and filters out the ones that contain 'myItem'.
The loop works, however, it returns results in varied order. Is there a way to sort the result of the array so
that it lists them alphanumerically?
foreach($itemArray as $item) {
if (preg_match('/myItem/',$item))
echo '$item';
}
I don't have much experience with php and would definitely appreciate the help! Thank you!
PHP supports lots of ways to sort arrays, see how they work here. You could run it as asort($itemArray).
The right way to solve this is by sorting the array prior to outputting it. Something along the lines of:
asort($itemArray);
foreach($itemArray as $item) {
if (preg_match('/myItem/',$item))
array[index++] = $item;
}
I woud like to sort an array which typically includes names and email addresses. The problem is that the email addresses appear last even though they may start with 'a'
e.g.
$myarray = ("Alex Mayfeild", "David Beckham", "Oliver Twist", "ant.stev#wherever.com", "peter.pan#neverland.com", ........) //and so on
Upon sorting the array using php's sort function "ant.stev#wherever.com" will appear close to the end even though the functionality I would like to achieve is for him to appear after Alex.
natcasesort and natsource functions based on natural ordering seem to fail. Correction: natcasesource works it returns true when working as stated in docs. Thanks #meagar
Is there anyway to achieve the requested functionality. Thanks for any help guys. It is very much appreciated.
sort() is case sensitive, as it sorts based on the letters ASCII value.
Try natcasesort(), if you want too "sort an array using a case insensitive 'natural order' algorithm".
Seems to me that sort($myarray, SORT_STRING|SORT_FLAG_CASE); should sort the array the way you want.
I am fetching an array of floats from my database but the array I get has converted the values to strings.
How can I convert them into floats again without looping through the array?
Alternatively, how can I fetch the values from the database without converting them to strings?
EDIT:
I am using the Zend Framework and I am using PDO_mysql. The values are stored one per column and that is a requirement so I can't serialize them.
array_map('floatval', $array) only works on single dimensional arrays.
I can't floatval the single elements when I use them because I have to pass an array to my flash chart.
The momentary, non-generic solution is to extract the rows and do array_map('floatval',$array) with each row.
You could use
$floats = array_map('floatval', $nonFloats);
There is the option PDO::ATTR_STRINGIFY_FETCHES but from what I remember, MySQL always has it as true
Edit: see Bug 44341 which confirms MySQL doesn't support turning off stringify.
Edit: you can also map a custom function like this:
function toFloats($array)
{
return array_map('floatval', $array);
}
$data = array_map('toFloats', $my2DArray);
How are you getting your data? mysql, mysqli or PDO, some other way or even some other database?
you could use array_map with floatval like so:
$data = array_map('floatval', $data);
but that still executes a loop and i think it assumes you only have one column in your data.
you're probably best of casting to float when you use your value, if you have to. php is likely to do a good job of interpreting it right anyway.
LOL... are you working on the same project I am tharkun?
I just finished (last night) creating something, in a ZF based project, that uses pdo_mysql to retrieve and format data and then output it as xml for use in a flash piece. The values were going in as strings but needed to be floats.
Since I'm also the one who wrote the part that gets the data and the one who created the database I just made sure the data was converted to float before it went into the database.
I simply cast the values as float as part of some other formatting, for what it is worth.
protected function _c2f($input)
{
$input = (float)$input;
$output = round(($input * 1.8) + 32, 2);
return $output;
}
I found an easy way for this operation.
You can do this just by adding foreach loop to your code. foreach loop is used to fetch your array string data one by one. and then, you can simply convert this by function number_format. i used 2 place after convert to float value. i.e it used to print value after dot value 2 place.
$example= array("12.20", "15.05", "55.70");
foreach($example as $float)
{
$update_value = number_format($float,2);
echo $update_value."<br>";
}
Not sure what you're asking here? You can cast a string to a float, using (float) $string, but since PHP is dynamically typed, that will happen anyway, when needed. There is no reason to do an explicit cast.
What are you using floating point values for?