Sorting CSV Data By A Column With PHP - php

I've looked on Stack Overflow with no solution that seems to work. Know that I'm a newbie!
Suppose I have a file (data.csv) with the following contents:
year,total
1990,57.58
2011,73.28
1880,54.67
1996,53.41
1950,53.22
1979,52.76
1876,52.62
1883,52.35
1882,52.12
2018,52.23
...then import the data with PHP:
$csv = array_map('str_getcsv', file('data.csv'));
How would I sort both the year and total by the total column in ascending order (such that 1882/52.12 are under $csv[0] in the array and 2011/73.28 are under $csv[10]?
The following and a print($csv); does not seem to be getting the items in the right order:
function compare($a, $b) {
return ($b[0][1] - $a[0][1]);
}
usort($csv, "compare");
Do I need to use typecasting? Thank you!

This will do the trick:
You have to modify the function like this:
function compare($a, $b)
{
// here, comparing "total" column of each row:
return $a[1] >= $b[1] ? 1 : -1;
}
And the new ordering will be:
Array
(
[0] => Array
(
[0] => 1882
[1] => 52.12
)
[1] => Array
(
[0] => 2018
[1] => 52.23
)
[2] => Array
(
[0] => 1883
[1] => 52.35
)
[3] => Array
(
[0] => 1876
[1] => 52.62
)
[4] => Array
(
[0] => 1979
[1] => 52.76
)
[5] => Array
(
[0] => 1950
[1] => 53.22
)
[6] => Array
(
[0] => 1996
[1] => 53.41
)
[7] => Array
(
[0] => 1880
[1] => 54.67
)
[8] => Array
(
[0] => 1990
[1] => 57.58
)
[9] => Array
(
[0] => 2011
[1] => 73.28
)
)

Three problems with your comparison function.
The items that will be compared in your comparison function are going to be arrays corresponding to rows from your CSV file. For example, $a and $b will be things like [1990,57.58] and [1950,53.22].
When you refer to those items in your comparison function, you're looking at index [0][1], but that doesn't exist; the arrays don't have that second dimension. $a[0][1] and $b[0][1] will both be null, so no sorting happens. (You might think you'd get some kind of warning or notice for trying to refer to an int or float with an array index, but you won't, just one of the weird things about PHP.)
You want to sort in ascending order, but putting $b first will sort in descending order.
The comparison function should return an int greater than, less than, or equal to zero depending on the result of the comparison, but yours will return a float. There are various way to make it return an int. The other answer shows how to do it with a ternary expression. If you're using PHP 7, you can use the combined comparison operator, like this:
function compare($a, $b) {
return $a[1] <=> $b[1];
}
Also, you don't need to define a named comparison function, you can use an anonymous function for the second argument if you like.
usort($csv, function($a, $b) {
return $a[1] <=> $b[1];
});

Related

PHP and prevent uasort function from sorting if values are equivalent

I'm using an array with PHP's uasort function. If $a[0]['date'] == $b[0]['date'], then I do not want to sort.
Anyway, my code will sort anyway. How could I prevent it from doing so?
Here is my array:
And here is the array:
Array (
[2764] => Array (
[status] => 0
[0] => Array (
[date] => 2000-01-01
)
[1] => Array (
[date] => 2016-01-16
)
)
[5974] => Array (
[status] => 0
[0] => Array (
[date] => 2000-01-01
)
[1] => Array (
[date] => 2010-12-13
)
)
)
And here is how I'm trying to sort:
uasort($arr, function($a, $b)
{
if ($a['status'] == $b['status'])
{
if ($a[0]['date'] == $b[0]['date'])
{
return 0; # I do not want to sort here, but this will sort anyway - why is that so?
}
else
{
return strcmp($a[0]['date'], $b[0]['date']);
}
}
else
{
return $b['status'] - $a['status'];
}
});
How could I sort by indexes if dates are same? I mean sorting by indexes 2764 and 5974.
As in documentation:
If two members compare as equal, their relative order in the sorted array is undefined.
So you have to introduce extra value, such as original_order and sort by it equal entries.

Sort an array (looking a specific value) based on another array

I have this array of options, and some value of an internal array is the "ID"
[options] => Array (
[0] => Array (
[id] => 1088
[label] => John
)
[1] => Array (
[id] => 1089
[label] => Peter
)
[2] => Array (
[id] => 1050
[label] => Mary
)
....
On the other hand, I have this array:
$array_sort = array(1089, 1050, 1088, ...);
I would like the options array of the first array is sorted (looking the "id") based on the $array_sort.
I know how to do it in a very dirty way (with a lot of loops and temporary arrays), but I guess there's some smart solution of array_* functions to do this.
Thank you !
You could use array_filter to limit the options to only those in the sorted array, then usort to sort them based on their position in the $array_sort array using array_search:
$sorted = array_filter($options, function($arr) use($array_sort) {
return in_array($arr['id'], $array_sort);
});
usort($sorted, function($a, $b) use($array_sort) {
return array_search($a['id'], $array_sort) - array_search($b['id'], $array_sort);
});
// $sorted should now be the sorted array

Intersect (inner join) two arrays with different key names

I have following two multidimensional arrays:
First array:
$array_1_data = Array (
[0] => Array ( [id] => 1 [name] => IT [slug] => it )
[1] => Array ( [id] => 2 [name] => Accounting [slug] => accounting )
)
Second array:
$array_2_data = Array (
[0] => Array ( [cid] => 3 [jid] => 24061 )
[1] => Array ( [cid] => 1 [jid] => 24062 )
)
Expected result:
$some_array = Array (
[0] => Array ( [id] => 1 [name] => IT [slug] => it )
)
I won't mind having [cid] in the result.
I want to intersect these two arrays by [id] of the first array and [cid] of the second array, like inner join in MySQL. I have basic foreach and if else logic for this purpose but speed is a priority now so I'm looking for non-looped solution. For better understanding here is the basic looped solution:
foreach ($array_1_data as $array_1_row ) {
foreach ($array_2_data as $array_2_row ) {
if ($array_2_row['cid'] == $array_1_row['id']) {
//intersection iteration
}
}
}
I tried array_uintersection as follows:
array_uintersect($array_1_data, $array_2_data, function($a1, $a2){
$diff1 = strcasecmp($a1['id'], $a2['cid']);
if ($diff1 != 0) return $diff1;
return 0;
});
But it gives me undefined index 'id'. I checked this question: Comparing two arrays with different key names. First answer for this question gives a looped solution which I want to avoid. Second answer suggests changing SQL structure but I have no control over that. So,
Is there really a non-looped fast solution to this kind of situation?
The solution using array_uintersect_uassoc function:
$result = array_uintersect_uassoc($array_1_data, $array_2_data, function($a, $b){
return strcasecmp($a['id'], $b['cid']);
}, function($a, $b){
return (int) [$a, $b] == ['id', 'cid'];
});
print_r($result);
The output:
Array
(
[0] => Array
(
[id] => 1
[name] => IT
[slug] => it
)
)
According yo your condition: to intersect these two arrays by [id] of the first array and [cid] of the second array, we should consider a key comparison function for those keys only ['id', 'cid'].
Having the needed keys on each comparison step it only remain to compare their values(with value compare function)
http://php.net/manual/en/function.array-uintersect-uassoc.php
DEMO link

PHP sorting a set of multidimensional arrays

I have an array which contains another array with a distance and ID in it. I need to sort the distance part of the array, so the ID remains correlated with it's respective distance.
Eg.
array
(
[0] => array(
[0] => 170
[1] => 123abc
)
[1] => array(
[0] => 150
[1] => 456def
)
)
Now, I want to sort the distances ascending so my sorted output would look like:
array
(
[0] => array(
[0] => 150
[1] => 456def
)
[1] => array(
[0] => 170
[1] => 123abc
)
)
As 150 is smaller than 170, it has 'moved' up.
I've looked at the PHP functions for this; array_multisort() etc. however these only seem to sort the values within the arrays rather than a set of arrays.
Any help appreciated.
EDIT:
There isn't a fixed number of items within the first array - it ranges from 1 to infinity.
use usort
usort($yourArray, function($a, $b) {
return $a[0] - $b[0]; // index 0 is your 150 or 170
});

Sorting in php Arrayss

My sql table consists of ID,Book name,Genre and ratings.Currently my array from my sql table looks like this (output)
Array (
[book] => Array (
[0] => Array
( [0] => 1
[1] => book one
[2] => Fantasy/Horror
[4] => 8.9 )
[1] => Array (
[0] => 2
[1] => book two
[2] => Comedy
[4] => 8.3 ) ) )
i want to sort this array to DESC by ID
Also in the future by title.
The array variable is $book so i wrote ksort($book) also tried arsort
for some reason it doesnt work? Is it because of the array? Thanks!
IF you are able to:
Use SQL sorting instead, because of the speed and flexibility (Use db-engine where it's appropiate) Only use array-functionality if you really need to! :-)
Do something like:
SELECT ID,Book name,Genre, ratings ORDER BY ID DESC
OR
If you have still have to use array sorting, use usort() in PHP:
<?php
//Book array
$bookArray['book'][0] = array(2, 'book one', 'Fantasy/Horror', 8.9);
$bookArray['book'][1] = array(1, 'book two ', 'Comedy', 8.3);
function sortByIndex($a, $b) {
return $a[0] - $b[0];
}
usort($bookArray['book'], 'sortByIndex');
echo 'RESULT=' . print_r($bookArray,true);
?>
Results in this output:
RESULT=Array ( [book] => Array ( [0] => Array ( [0] => 1 [1] => book two [2] => Comedy [3] => 8.3 ) [1] => Array ( [0] => 2 [1] => book one [2] => Fantasy/Horror [3] => 8.9 ) ) )
Book two comes first here, because in my example I set the first index to be 1 with value 'book two'.
The easiest way is to add this to your SQL statement at the end:
ORDER BY id DESC
Also if you really want to know how to do it in PHP you would do it this way:
function cmp($a, $b)
{
if ($a[0] == $b[0]) {
return 0;
}
return ($a[0] > $b[0]) ? -1 : 1;
}
usort($array['book'], "cmp");
Just you need to change your Select Statement. It should be something like this -
select id,bookname,genre,ratings from yourtable ORDER BY id DESC,bookname;

Categories