webForumDet fria alternativet

Sortera array?

PHP

15 svar · 1 297 visningar · startad av drew

Medlem sedan mars 2007845 inlägg
Frågan#1

Jag har en array som innehåller en array där ett av värdena är filnamn med sökväg.
Ex:

a_fil
a_katalog/underkatalog/a_fil
a_katalog/underkatalog/b_fil
a_katalog/b_fil
a_katalog/b_fil
b_katalog/underkatalog/a_fil
b_katalog/underkatalog/b_fil
b_katalog/b_fil
b_katalog/b_fil
b_fil

Jag vill sortera denna array alfabetiskt. Men filerna ska vara först. Också i underkatalogerna. Alltså ska b_fil komma före a_katalog.

Varje sträng är en fil, om någon slutar med / skickas allt tillbaka till användaren med ett rött "HÖRRU".

Just nu står det helt still och jag kommer inte på något bra sätt att sortera efter. Utom att blanda in / i sorteringen. Jag funderade på att lägga till ett fält till i arrayen och sätta värden i den med explode(), men det känns lite överarbetat.

Någon som har något bra tips?

/D

Medlem sedan nov. 200373 inlägg
#2

Såhär kanske, om jag förstod dig rätt...

<?php
$values = array(
	array("id" => 1, "filename" => "b_katalog/underkatalog/a_fil")
	,array("id" => 2, "filename" => "b_katalog/underkatalog/b_fil")
	,array("id" => 2, "filename" => "b_katalog/b_fil")
	, array("id" => 3, "filename" => "a_katalog/underkatalog/c_fil")
	, array("id" => 4, "filename" => "a_fil")
	, array("id" => 5, "filename" => "b_fil")
);

$filenames = array();
foreach($values as $key => $row){
	$filenames[$key] = basename($row["filename"]);
}
array_multisort($filenames, SORT_STRING, $values);
print_r($values);
Medlem sedan mars 2007845 inlägg
#3

Då sorteras dom ju rent i bokstavsordning. /a_katalog/b_fil sorteras före /b_fil.

Jag funderade på att först sortera dom i bokstavsordning och sen efter antalet / på något sätt som jag inte kommit på än.

Medlem sedan nov. 200373 inlägg
#4

Den här sorteras först på filnamn och sen på antalet /

<?php
$values = array(
    array("id" => 1, "filename" => "b_katalog/underkatalog/a_fil")
    ,array("id" => 2, "filename" => "b_katalog/underkatalog/b_fil")
    ,array("id" => 2, "filename" => "b_katalog/b_fil")
    ,array("id" => 3, "filename" => "a_katalog/underkatalog/c_fil")
    ,array("id" => 4, "filename" => "a_fil")
    ,array("id" => 5, "filename" => "b_fil")
);

$filenames = array();
$subdirectories = array();
foreach($values as $key => $row){
    $filenames[$key] = basename($row["filename"]);
    $subdirectories[$key] = count(explode("/", $row["filename"]));
}
array_multisort($filenames, SORT_STRING, $subdirectories, SORT_ASC, $values);
print_r($values);
Medlem sedan mars 2007845 inlägg
#5

Ska testa det. Tack.

Medlem sedan mars 2007845 inlägg
#6

Nu har jag testat och experimenterat.

Att sortera efter antalet / funkade inte så bra. Eller visst funkade det, men resultatet blev fel.

Tack för pekandet i rätt riktning.

Detta sorterar i bokstavsordning med filerna först. Även i underkataloger.

$arr = array(
	array('id' => 1, 'file' => 'b_katalog/underkatalog/a_fil'),
	array('id' => 2, 'file' => 'b_katalog/underkatalog/b_fil'),
	array('id' => 2, 'file' => 'b_katalog/b_fil'),
	array('id' => 3, 'file' => 'a_katalog/underkatalog/c_fil'),
	array('id' => 4, 'file' => 'a_fil'),
	array('id' => 5, 'file' => 'b_fil'),
);

$filenames = $directories = array();
foreach($arr as $key => $value)
{
	$filenames[$key] = basename($value['file']);
	$directories[$key] = dirname($value['file']);
}
array_multisort($directories, SORT_STRING, $filenames, SORT_STRING, $arr);
print_r($arr);
Medlem sedan feb. 20034 441 inlägg
#7

Jag har en array som ser ut såhär:

Array
(
    [1] => Array
        (
            [id] => 1
            [name] => Apple
            [amount] => 5
        )

    [2] => Array
        (
            [id] => 2
            [name] => Blueberry
            [amount] => 7
        )

    [3] => Array
        (
            [id] => 3
            [name] => Pear
            [amount] => 5
        )

    [4] => Array
        (
            [id] => 4
            [name] => Tomato
            [amount] => 5
        )

    [5] => Array
        (
            [id] => 5
            [name] => Other
            [amount] => 5
        )

Nu måste jag sortera den efter amount i fallande ordning men har fastnat fullständigt. Har hittat diverse funktioner via Google men får ingen av dom att fungera.

Har tittat på bl.a. multisort osv. på php.net men utan att lösa det. Någon som vet?

Tack!

Medlem sedan mars 20007 896 inlägg
#8

usort() letar du efter. Nedanstående förutsätter att 'amount' alltid är numeriskt.

function __amount_sort($a, $b) {
    return $b['amount'] - $a['amount'];
}

usort($yourArray, '__amount_sort');
Medlem sedan feb. 20034 441 inlägg
#9

SPiN skrev:

usort() letar du efter. Nedanstående förutsätter att 'amount' alltid är numeriskt.

Så jävla snyggt, tack ska du ha!
Och ja, amount är alltid numeriskt. :)

Medlem sedan feb. 20034 441 inlägg
#10

Nu verkar jag ha ett litet problem med det här. Det är så att "amount" kan vara ett decimaltal och då blir sorteringen fel. Såhär blir det efter att jag sorterat med usort:

5.9, Apple
6.05, Pear
6.6, Grape
6.5, Tomato
6.8, Foo
6.7, Bar

Hur löser jag det? Antar att jag måste subtypkonvertera eller så, men hur och var ska jag göra det? Funkar som så att varje "sak" har ett startvärde (t.ex. 0.10, 0.35) och sen adderas tal i en for-loop.

När loopen är klar ska arrayen sorteras.

Medlem sedan mars 20007 896 inlägg
#11

Du _kan_ göra om typen i din sorteringsfunktion;

function __amount_sort($a, $b) {
    return floatval($b['amount']) - floatval($a['amount']);
}

Dock så bör självklart värdet lagras som ett flyttal i din array, och hursomhelst är det antagligen floatval() du bör använda.

Medlem sedan mars 20007 896 inlägg
#12

Nu var jag alldelles för snabb ser jag. Det blir lite annorlunda när det är flyttal;

function __amount_sort($a, $b) {
	if ((float)$a['amount'] == (float)$b['amount'])
		return 0;
	
	return (floatval($a['amount']) > floatval($b['amount'])) ? 1 : -1;
}

Den kortare varianten fungerar enbart på heltal.

Medlem sedan feb. 20034 441 inlägg
#13

Tack! Hinner tyvärr inte testa nu, är på väg ut, men ska prova direkt imorgonbitti, återkommer!

Medlem sedan feb. 20034 441 inlägg
#14

Nu har jag testat och sorteringen blir nu rätt. Fast ordningen blir fel nu. Den sorterar array'en stigande och inte fallande som tidigare.

Det spelar eg. ingen roll, kan köra min for-loop baklänges istället och uppnå samma sak, men lite intressant att ta reda på varför och går det att göra något åt det på ett enkelt sätt?

Medlem sedan mars 20007 896 inlägg
#15

För att jag hade missat att du skulle sortera fallande :-) Åtgärd: Ändra ordningen i jämförelsen i din sorteringsfunktion:

function __amount_sort($a, $b) {
    if ((float)$a['amount'] == (float)$b['amount'])
        return 0;
    
    return (floatval($a['amount']) < floatval($b['amount'])) ? 1 : -1;
}
Medlem sedan feb. 20034 441 inlägg
#16

SPiN skrev:

För att jag hade missat att du skulle sortera fallande :-) Åtgärd: Ändra ordningen i jämförelsen i din sorteringsfunktion:

Ahh, enkelt! Tack ska du ha!

271 ms totalt · 4 externa anrop · v20260731065814-full.a51de22e
128 ms — deklarationer (db)
0 ms — hämta statistik (cache)
140 ms — hämta tråd, inlägg och bilagor (db)
121 ms — ändringar (db)