Avatar billede h_thunbo Nybegynder
20. marts 2012 - 15:43 Der er 22 kommentarer og
1 løsning

Sortering fra strcmp til ?? når det er tal

Hej Eksperter.
Jeg har søgt og søgt men kan ikke finde noget godt svar på mit problem. Jeg har en sorterings funktion der skal sortere mit array ($data), som er lavet med et udtræk fra databasen. Der ser således ud:

function usort_reorder($a,$b){
  $orderby = (!empty($_REQUEST['orderby'])) ? $_REQUEST['orderby'] : 'title';
  $order = (!empty($_REQUEST['order'])) ? $_REQUEST['order'] : 'asc';
  $result = strcmp($a[$orderby], $b[$orderby]);
  return ($order==='asc') ? $result : -$result;
}
usort($data, 'usort_reorder');

Mit problem er når det er tal der skal sorteres efter. Jeg ved jeg ikke kan bruge string compare, men hvad skal jeg så bruge?
Avatar billede olebole Juniormester
20. marts 2012 - 16:02 #1
<ole>

Prøv:

function usort_reorder($a,$b){
  $orderby = (!empty($_REQUEST['orderby'])) ? $_REQUEST['orderby'] : 'title';
  $order = (!empty($_REQUEST['order'])) ? $_REQUEST['order'] : 'asc';
  if (is_string($a[$orderby])) $result = strcmp($a[$orderby], $b[$orderby]);
  else  $result = $a[$orderby]>$b[$orderby] ? 1 : $a[$orderby]<$b[$orderby] ? -1 : 0;
  return ($order==='asc') ? $result : -$result;
}

/mvh
</bole>
Avatar billede h_thunbo Nybegynder
20. marts 2012 - 16:06 #2
Hmm... Jo det virker da sån lidt, men ikke helt. Den sortere først og fremmest efter det første cifre. dvs:
1
18
2
22
23
3
osv osv...
Avatar billede olebole Juniormester
20. marts 2012 - 16:57 #3
Ja, det er klart. Prøv dette i stedet:

else  $result = $a[$orderby]==$b[$orderby] ? 0 : $a[$orderby]>$b[$orderby] ? 1 : -1;
Avatar billede h_thunbo Nybegynder
20. marts 2012 - 17:05 #4
Du er da også alle steder :-)
Det løste ikke problemet, den sortere stadig som ovenfor...
Avatar billede olebole Juniormester
20. marts 2012 - 17:13 #5
Det lyder sært! Prøv lige at vise et eksempel på dit data array
Avatar billede olebole Juniormester
20. marts 2012 - 17:16 #6
Et forsimplet som dette fungerer fint:

<?php
$data = array(13,4,12,56,5,6,1,2,23);

function usort_reorder($a, $b) {
    return $a==$b ? 0 : $a>$b ? 1 : -1;
}
usort($data, 'usort_reorder');

var_dump($data);
?>
Avatar billede h_thunbo Nybegynder
20. marts 2012 - 17:19 #7
Her er et sorteret eksempel:

Array (
  [0] => Array ( [id] => 1 [text_da] => % [text_en] => % )
  [1] => Array ( [id] => 18 [text_da] => ton [text_en] => ton )
  [2] => Array ( [id] => 2 [text_da] => timer [text_en] => hours )
  [3] => Array ( [id] => 22 [text_da] => m3 pr. minut [text_en] => m3 per minute )
)
Avatar billede h_thunbo Nybegynder
20. marts 2012 - 17:31 #8
Ja, dit simple eksempel virker fint! Så kommer de i rækkefølge. Men hvad er det så der kikser hvis 'orderby' = id?
Avatar billede olebole Juniormester
20. marts 2012 - 17:35 #9
Jamen, det gør det heller ikke. Prøv dette:

<?php
$data = array (
  array('id' => 1, 'text_da' => '%', 'text_en' => '%'),
  array('id' => 18, 'text_da' => 'ton', 'text_en' => 'ton'),
  array('id' => 2, 'text_da' => 'timer', 'text_en' => 'hours'),
  array('id' => 22, 'text_da' => 'm3 pr. minut', 'text_en' => 'm3 per minute')
);
$_REQUEST['orderby'] = 'id';

function usort_reorder($a,$b){
  $orderby = (!empty($_REQUEST['orderby'])) ? $_REQUEST['orderby'] : 'title';
  $order = (!empty($_REQUEST['order'])) ? $_REQUEST['order'] : 'asc';
  if (is_string($a[$orderby])) $result = strcmp($a[$orderby], $b[$orderby]);
  else  $result = $a[$orderby]==$b[$orderby] ? 0 : $a[$orderby]>$b[$orderby] ? 1 : -1;
  return ($order==='asc') ? $result : -$result;
}

usort($data, 'usort_reorder');

var_dump($data);
?>

Det giver hos mig følgende resultat:

array
  0 =>
    array
      'id' => int 1
      'text_da' => string '%' (length=1)
      'text_en' => string '%' (length=1)
  1 =>
    array
      'id' => int 2
      'text_da' => string 'timer' (length=5)
      'text_en' => string 'hours' (length=5)
  2 =>
    array
      'id' => int 18
      'text_da' => string 'ton' (length=3)
      'text_en' => string 'ton' (length=3)
  3 =>
    array
      'id' => int 22
      'text_da' => string 'm3 pr. minut' (length=12)
      'text_en' => string 'm3 per minute' (length=13)
Avatar billede olebole Juniormester
20. marts 2012 - 17:39 #10
- og du kan også prøve dette:

<?php
$data = array (
  array('id' => 18, 'text_da' => 'ton', 'text_en' => 'ton'), 
  array('id' => 2, 'text_da' => 'timer', 'text_en' => 'hours'),
  array('id' => 1, 'text_da' => '%', 'text_en' => '%'),
  array('id' => 22, 'text_da' => 'm3 pr. minut', 'text_en' => 'm3 per minute')
);
shuffle($data);
$_REQUEST['orderby'] = 'id';
//$_REQUEST['order'] = 'desc';

function usort_reorder($a,$b){
  $orderby = (!empty($_REQUEST['orderby'])) ? $_REQUEST['orderby'] : 'title';
  $order = (!empty($_REQUEST['order'])) ? $_REQUEST['order'] : 'asc';
  if (is_string($a[$orderby])) $result = strcmp($a[$orderby], $b[$orderby]);
  else  $result = $a[$orderby]==$b[$orderby] ? 0 : $a[$orderby]>$b[$orderby] ? 1 : -1;
  return ($order==='asc') ? $result : -$result;
}

var_dump($data);
echo '<hr>';

usort($data, 'usort_reorder');

var_dump($data);
?>
Avatar billede olebole Juniormester
20. marts 2012 - 18:03 #11
PS: Er du helt sikker på, der er tale om tal? Det er vel ikke strenge som i:

$data = array (
  array('id' => '18', 'text_da' => 'ton', 'text_en' => 'ton'), 
  array('id' => '2', 'text_da' => 'timer', 'text_en' => 'hours'),
  array('id' => '1', 'text_da' => '%', 'text_en' => '%'),
  array('id' => '22', 'text_da' => 'm3 pr. minut', 'text_en' => 'm3 per minute')
);
Avatar billede h_thunbo Nybegynder
20. marts 2012 - 22:36 #12
Hej Ole
Ah... Du har jo ret (igen!)... Den tror id er en tekst streng...
Undskyld jeg lige smuttede, jeg havde "desværre" en aftale i biografen til en gang Hvidstensgruppen... Men nu er jeg tilbage resten af natten :-) Jeg får det her ud:
array(4) {
  [0]=> array(4) { ["id"]=> string(1) "1" ["text_da"]=> string(1) "%" ["text_en"]=> string(1) "%" }
  [1]=> array(4) { ["id"]=> string(2) "18" ["text_da"]=> string(3) "ton" ["text_en"]=> string(3) "ton" }
  [2]=> array(4) { ["id"]=> string(1) "2" ["text_da"]=> string(5) "timer" ["text_en"]=> string(5) "hours" }
  [3]=> array(4) { ["id"]=> string(2) "22" ["text_da"]=> string(12) "m3 pr. minut" ["text_en"]=> string(13) "m3 per minute" }
}

Så fejlen er jo i id'en. I databasen er det integer.
hmmm...
Avatar billede olebole Juniormester
20. marts 2012 - 22:48 #13
Hvordan trækker du data ud af databasen - og hvad gør du efterfølgende? Et eller andet sted må ID'et jo blive konverteret ... lad os prøve at spore det  =)
Avatar billede h_thunbo Nybegynder
20. marts 2012 - 22:54 #14
Jeg har rodet lidt med det og har fundet en løsning der virker... Ved bare ikke om jeg synes den er iorden for id er stadig en string? Den ser sån her ud:
function usort_reorder($a,$b){
  $orderby = (!empty($_REQUEST['orderby'])) ? $_REQUEST['orderby'] : 'title';
  $order = (!empty($_REQUEST['order'])) ? $_REQUEST['order'] : 'asc';
  if (is_string($a[$orderby])) $result = strcmp($a[$orderby], $b[$orderby]);
  else  $result = $a[$orderby]==$b[$orderby] ? 0 : $a[$orderby]>$b[$orderby] ? 1 : -1;
  if ($orderby == 'id'){
      return ($order==='asc') ? ($a>$b ? 1 : -1) : ($a<$b ? 1 : -1);
  }
  else{
      return ($order==='asc') ? $result : -$result; //Send final sort direction to usort
  }
}

usort($data, 'usort_reorder');


Jeg trækker dataerne ud her:
$query = "SELECT * FROM postfixes";
    $data = $wpdb->get_results($query, ARRAY_A);
Avatar billede olebole Juniormester
21. marts 2012 - 00:36 #15
Du kunne prøve denne kode:

$data = array (
  array('id' => '18', 'text_da' => 'ton', 'text_en' => 'ton'), 
  array('id' => '2', 'text_da' => 'timer', 'text_en' => 'hours'),
  array('id' => '1', 'text_da' => '%', 'text_en' => '%'),
  array('id' => '22', 'text_da' => 'm3 pr. minut', 'text_en' => 'm3 per minute')
);

var_dump($data);

function intIt($var) {
    $var['id'] = (int) $var['id'];
    return $var;
}
$data = array_map('intIt', $data);

var_dump($data);

Hvilket fører til, at du kunne skrive:

$query = "SELECT * FROM postfixes";
$data = $wpdb->get_results($query, ARRAY_A);
function intIt($var) {
    $var['id'] = (int) $var['id'];
    return $var;
}
$data = array_map('intIt', $data);
Avatar billede h_thunbo Nybegynder
21. marts 2012 - 10:47 #16
Ja, nu virker det. Du har stoppet min produktion af grå hår... For en tid i hvert fald... Men jeg tænker bare om ikke det var bedre at lave funktionen sådan at den selv finder ud af hvilke felter der er int og så køre funktionen, frem for at jeg selv skal gøre den opmærksom på hvad der er int.
Avatar billede olebole Juniormester
21. marts 2012 - 11:20 #17
Tjohh, men det er jo ikke så let. Det kræver, du spørger databasen, hvilken type de forskellige felter er af. Det ser ud, som om du bruger en WordPress klasse, og jeg tvivler på, den kan det(?)
Avatar billede h_thunbo Nybegynder
21. marts 2012 - 12:31 #18
Der må jeg melde pas, det ved jeg ikke? Nå, men Olebole, du må hellere få dine point, så må jeg lige tænke over hvordan jeg skal gøre en anden gang... Måske kommer der et nyt spørgsmål på et tidspunkt :-)
Avatar billede olebole Juniormester
21. marts 2012 - 12:55 #19
Ellers tak, jeg samler ikke point. Læg selv et svar og accepter det, så tråden lukkes  =)

Du kan normalt undersøge felternes type på denne måde i MySQL og i MySQLI - men om det kan lade sig gøre i den klasse, du bruger, ved jeg som sagt ikke
Avatar billede h_thunbo Nybegynder
21. marts 2012 - 13:06 #20
Okay, jamen helt fint, jeg kigger på dine links :-)
Løsningen blev at jeg trækker dataerne ud således:
$query = "SELECT * FROM yourshop_brands";
$data = $wpdb->get_results($query, ARRAY_A);
function intIt($var) {
  $var['id'] = (int) $var['id'];
  return $var;
}
$data = array_map('intIt', $data);


og sortere således:
function usort_reorder($a,$b){
  $orderby = (!empty($_REQUEST['orderby'])) ? $_REQUEST['orderby'] : 'title';
  $order = (!empty($_REQUEST['order'])) ? $_REQUEST['order'] : 'asc';
  if (is_string($a[$orderby])) $result = strcmp($a[$orderby], $b[$orderby]);
  else  $result = $a[$orderby]==$b[$orderby] ? 0 : $a[$orderby]>$b[$orderby] ? 1 : -1;
  return ($order==='asc') ? $result : -$result;
}
usort($data, 'usort_reorder');
Avatar billede olebole Juniormester
21. marts 2012 - 13:51 #21
Tror, jeg har fundet noget brugbart. Prøv lige denne kode og fortæl, hvad du får ud af det:

$query = "SELECT * FROM yourshop_brands";
$data = $wpdb->get_results($query, ARRAY_A);
$info = $wpdb->get_col_info('type');
var_dump($info);
Avatar billede h_thunbo Nybegynder
22. marts 2012 - 09:27 #22
Ja den skriver rigtig nok ud at at udtrækket består af "int" og "string"
array(4) {
  [0]=> string(3) "int"
  [1]=> string(6) "string"
  [2]=> string(6) "string"
}
Avatar billede olebole Juniormester
22. marts 2012 - 14:07 #23
Måske, du kan bruge det til at konvertere værdierne på. Allerbedst ville det nok være at skrive klassen om, så man slipper for at lappe på en dårlig kode. Det er jo helt vanvittigt, at en databaseklasse laver om på datatyper på data  :o|
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester