webForumDet fria alternativet

Sortera array?

15 svar · 1 297 visningar · startad av drew

drewMedlem sedan mars 2007748 inlägg
#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

pulseMedlem sedan nov. 200384 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);
drewMedlem sedan mars 2007748 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.

pulseMedlem sedan nov. 200384 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);
drewMedlem sedan mars 2007748 inlägg
#5

Ska testa det. Tack.

drewMedlem sedan mars 2007748 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);
MickeA.comMedlem sedan feb. 20034 528 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!

SPiNMedlem sedan mars 20005 832 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');
MickeA.comMedlem sedan feb. 20034 528 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. :)

MickeA.comMedlem sedan feb. 20034 528 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.

SPiNMedlem sedan mars 20005 832 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.

SPiNMedlem sedan mars 20005 832 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.

MickeA.comMedlem sedan feb. 20034 528 inlägg
#13

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

MickeA.comMedlem sedan feb. 20034 528 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?

SPiNMedlem sedan mars 20005 832 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;
}
MickeA.comMedlem sedan feb. 20034 528 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!

Genererad på 385 ms · cache AV · v20260730165559-full.f96bc7eb