WN

WN (https://www.wn.se/forum/index.php)
-   Serversidans teknologier (https://www.wn.se/forum/forumdisplay.php?f=4)
-   -   Sortera array av objekt (simpleXML) (https://www.wn.se/forum/showthread.php?t=1042297)

jayzee 2010-05-31 11:04

Sortera array av objekt (simpleXML)
 
Jag försöker få min array av objekt att sorteras efter inläggningsdatum (<added>..</added> i XML filen) i PHP men det verkar som jag inte riktigt förstår det här med sortering av objekt med fler dimensioner i usort...

Kan någon vänlig själ upplysa mig om vad det är jag gör för fel?

XML filen: http://pastebin.com/ZG07PGMc
Koden: http://pastebin.com/PWC8k09G

Arrayens uppbyggnad:
Kod:

SimpleXMLElement Object
(
    [car] => Array
        (
            [0] => SimpleXMLElement Object
                (
                    [id] => 4422263
                    [added] => 1272916867
                )
 
            [1] => SimpleXMLElement Object
                (
                    [id] => 4409040
                    [added] => 1272360932
                )
 
            [2] => SimpleXMLElement Object
                (
                    [id] => 4409043
                    [added] => 1274456478
                )
 
            [3] => SimpleXMLElement Object
                (
                    [id] => 4459271
                    [added] => 1274450187
                )
 
        )
 
)


KarlRoos 2010-05-31 16:11

usort($xml->car, [..] bör det ju vara ;)

jayzee 2010-05-31 18:39

Citat:

Ursprungligen postat av KarlRoos (Inlägg 20357530)
usort($xml->car, [..] bör det ju vara ;)

Om det bara var så... :) Tyvärr så fungerar det inte.

Följande kod:
Kod:

<?php
$xml = simplexml_load_file("test.xml");

function mysort($a, $b)
{
  if($a->added == $b->added) {
    return 0;
  }
  return ($a->added < $b->added) ? -1 : 1;
}

usort($xml->car, "mysort"); // Returnerar 0 = fail

foreach($xml->car as $car)
{
  echo $car->added . " (" . date('Y-m-d h:m', (int)$car->added) . ")<br />";
}
?>

genererar:
Kod:

1272916867 (2010-05-03 10:05)
1272360932 (2010-04-27 11:04)
1274456478 (2010-05-21 05:05)
1274450187 (2010-05-21 03:05)

vilket inte är sorterat :/

znap 2010-05-31 23:09

Jag tror inte att $xml->car returnerar en array. Du måste alltså själv göra en ny array som du sedan sorterar. Något i stil med:

Kod:

$car_data = array();
foreach($xml->car as $car)
  $car_data[(int)$car->added] = $car;

usort($car_data, "mysort");
...

ps. insåg precis att man riskerar att skriva över värden om bilarna är köpta vid samma tidpunkt. Gör därför en rekursiv funktion som ökar värdet om du lägger till ett fält med en nyckel som redan existerar, typ $car_data[get_unique_key((int)$car->added, $car_data)]...

jayzee 2010-06-01 07:09

Så det finns ingen annan lösning än att göra om array av objekt till vanlig array och sortera den då? Anledningen till att jag frågar är att jag helst vill behålla objektstrukturen och att varje objekt innehåller ca. 20 attribut (ej med i mitt exempel).

tartareandesire 2010-06-01 12:06

Citat:

Ursprungligen postat av jayzee (Inlägg 20357622)
Så det finns ingen annan lösning än att göra om array av objekt till vanlig array och sortera den då? Anledningen till att jag frågar är att jag helst vill behålla objektstrukturen och att varje objekt innehåller ca. 20 attribut (ej med i mitt exempel).

Om det inte finns någon inbyggd sorteringsfunktion i objektet så kan det omöjligen veta hur det ska sorteras, eller hur? Alternativet är att bygga en egen sorteringsfunktion vilket kanske är motiverat i ditt fall men vi vet ju inte direkt hur ditt system är uppbyggt.

jayzee 2010-06-01 13:25

Citat:

Ursprungligen postat av tartareandesire (Inlägg 20357653)
Om det inte finns någon inbyggd sorteringsfunktion i objektet så kan det omöjligen veta hur det ska sorteras, eller hur? Alternativet är att bygga en egen sorteringsfunktion vilket kanske är motiverat i ditt fall men vi vet ju inte direkt hur ditt system är uppbyggt.

Finns inget system tyvärr. Bara den XML filen som hämtas av ett cronjob och som jag läser in med SimpleXML och försöker få objekten sorterade efter 'added' fältet :)
Original XML filen innehåller dock fler attribut förrutom 'added' i varje objekt men det är oviktigt i detta sammanhang.

qson 2010-06-01 14:05

Citat:

Ursprungligen postat av jayzee (Inlägg 20357666)
Finns inget system tyvärr. Bara den XML filen som hämtas av ett cronjob och som jag läser in med SimpleXML och försöker få objekten sorterade efter 'added' fältet :)
Original XML filen innehåller dock fler attribut förrutom 'added' i varje objekt men det är oviktigt i detta sammanhang.

Gör om objektlistan till en array, sedan kan du sortera den med valfri sorteringsmetod.

znap:s kod bör funka om du tar bort indexet.

PHP-kod:

$car_data = array();
foreach(
$xml->car as $car)
  
$car_data[] = $car;

/* Sorteringsfunktionen är saxad från php-manualen (usort) */
function sortByAdded($car1,$car2) {
    if (
$car1->added == $car2->added) {
        return 
0;
    }
    return (
$car1->added $car2->added) ? -1;
}

usort($car_data"sortByAdded"); 


jayzee 2010-06-01 15:00

Det gjorde susen - tusen tack qson!

En modifiering man måste göra är explicit omvandla 'added' till int eller string då man inte kan jämföra attribut med strängar, då funkar det inte. Ändringen:

PHP-kod:

function sortByAdded($car1,$car2) { 
    if ((int)
$car1->added == (int)$car2->added) { 
        return 
0
    } 
    return ((int)
$car1->added < (int)$car2->added) ? -1



Förstår dock inte varför KarlRoos förslag inte fungerade (även med typecasting)...

qson 2010-06-01 16:32

CarlRoos förslag fungerar inte därför att $xml->car inte är en array. Det är ett XML-objekt med en iterator (som gör att den fungerar med foreach).
sort-funktionerna fungerar bara med arrayer. Inte med iterator-objekt.

jayzee 2010-06-01 19:09

Citat:

Ursprungligen postat av qson (Inlägg 20357702)
CarlRoos förslag fungerar inte därför att $xml->car inte är en array. Det är ett XML-objekt med en iterator (som gör att den fungerar med foreach).
sort-funktionerna fungerar bara med arrayer. Inte med iterator-objekt.

Tackar... :D

martine 2010-06-07 09:33

Jag rekommenderar att kika på XSL som fixar sådana problem på ett kick (kanske lite överkurs för ditt exempel men det är nog vad jag skulle använt).


Alla tider är GMT +2. Klockan är nu 08:36.

Programvara från: vBulletin® Version 3.8.2
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Svensk översättning av: Anders Pettersson