Попытка отсортировать ассоциативный массив в PHP - PullRequest
0 голосов
/ 27 октября 2018

Я пытаюсь отсортировать этот ассоциативный массив в PHP, сортируя по полю name

$fonts = array(
    0 => ["index" => 0, "name" => "Arial", "path" => "assets/fonts/arial.ttf"],
    1 => ["index" => 1, "name" => "Times", "path" => "assets/fonts/times.ttf"],
    2 => ["index" => 2, "name" => "Roboto", "path" => "assets/fonts/roboto.ttf"],
    3 => ["index" => 3, "name" => "AlexBrush", "path" => "assets/fonts/AlexBrush-Regular.ttf"],
);

Я пытаюсь отсортировать записи по имени, но сохранить ключи, связанные ссама запись, поэтому я хочу:

 $fonts = array(
    3 => ["index" => 3, "name" => "AlexBrush", "path" => "assets/fonts/AlexBrush-Regular.ttf"],
    0 => ["index" => 0, "name" => "Arial", "path" => "assets/fonts/arial.ttf"],
    2 => ["index" => 2, "name" => "Roboto", "path" => "assets/fonts/roboto.ttf"],
    1 => ["index" => 1, "name" => "Times", "path" => "assets/fonts/times.ttf"],
);

Вот минимальный код, который выявляет проблему (PHP +7):

function cmp($a, $b)
{
    return strcmp($a["name"], $b["name"]);
}

$fonts = array(
    0 => ["index" => 0, "name" => "Arial", "path" => "assets/fonts/arial.ttf"],
    1 => ["index" => 1, "name" => "Times", "path" => "assets/fonts/times.ttf"],
    2 => ["index" => 2, "name" => "Roboto", "path" => "assets/fonts/roboto.ttf"],
    3 => ["index" => 3, "name" => "AlexBrush", "path" => "assets/fonts/AlexBrush-Regular.ttf"],
);

uasort($fonts, "cmp");

for($i = 0; $i < 4; $i++)
{
    echo "<br/>".$fonts[$i]["name"];
}

Я использую uasort() так как он должен сохранять ключи связанными при сортировке массива.К сожалению, если я распечатываю массив, я получаю тот же порядок, то есть:

Arial
Times
Roboto
AlexBrush

Ответы [ 4 ]

0 голосов
/ 28 октября 2018

Если вы собираетесь продолжать использовать for(), вам действительно нужно переиндексировать ключи первого уровня - что не составляет особого труда, поскольку у вас все еще сохраняются оригинальные числовые идентификаторы в элементах index.

В соответствии с этой логикой, я могу порекомендовать два разных однострочных.

  1. array_multisort(array_column($fonts, 'name'), $fonts);
  2. usort($fonts, function($a, $b){return $a['name'] <=> $b['name'];});

Демо

0 голосов
/ 27 октября 2018

Do sort по name , подобным образом, и цикл с использованием foreach()

<?php

$fonts = array(
    0 => ["index" => 0, "name" => "Arial", "path" => "assets/fonts/arial.ttf"],
    1 => ["index" => 1, "name" => "Times", "path" => "assets/fonts/times.ttf"],
    2 => ["index" => 2, "name" => "Roboto", "path" => "assets/fonts/roboto.ttf"],
    3 => ["index" => 3, "name" => "AlexBrush", "path" => "assets/fonts/AlexBrush-Regular.ttf"],
);

uasort($fonts, function($a, $b) {
    return strcmp($a['name'], $b['name']);
});

print_r($fonts);

foreach($fonts as $font){
 echo $font["name"].PHP_EOL;
}

?>

EDIT: На основе комментария OP,

 $indexed_array = array_column($fonts,'name','index'); // array column map name by index
 print_r($indexed_array); 
 echo $indexed_array[3];

DEMO: https://3v4l.org/W7BOH

0 голосов
/ 27 октября 2018

Вы можете использовать array_column, чтобы сделать массив ассоциативным, а затем отсортировать с помощью ksort (сортировка по ключу).

$fonts = array_column($fonts, null, "name");
ksort($fonts);
$fonts = array_values($fonts);
var_dump($fonts);

Вывод:

array(4) {
  [0]=>
  array(3) {
    ["index"]=>
    int(3)
    ["name"]=>
    string(9) "AlexBrush"
    ["path"]=>
    string(34) "assets/fonts/AlexBrush-Regular.ttf"
  }
  [1]=>
  array(3) {
    ["index"]=>
    int(0)
    ["name"]=>
    string(5) "Arial"
    ["path"]=>
    string(22) "assets/fonts/arial.ttf"
  }
  [2]=>
  array(3) {
    ["index"]=>
    int(2)
    ["name"]=>
    string(6) "Roboto"
    ["path"]=>
    string(23) "assets/fonts/roboto.ttf"
  }
  [3]=>
  array(3) {
    ["index"]=>
    int(1)
    ["name"]=>
    string(5) "Times"
    ["path"]=>
    string(22) "assets/fonts/times.ttf"
  }
}

Это означает, что вы можете выполнить итерацию массива какВы сделали в своем вопросе.

https://3v4l.org/pJXfp


Я вижу, что вы спрашиваете, как получить имя индекса 3.

В этом случае снова используйте array_columnсделать его ассоциативным по индексу.

https://3v4l.org/nCtJf

$fonts = array_column($fonts, null, "name");
ksort($fonts);
$fonts = array_column($fonts, null, "index");

echo $fonts[3]["name"]; //AlexBrush
0 голосов
/ 27 октября 2018

Поскольку вы используете ...

for($i = 0; $i < 4; $i++)
{
    echo "<br/>".$fonts[$i]["name"];
}

для печати значений, вы используете индекс в числовом порядке для их отображения.

Если вместо этого вы использовали ...

print_r($fonts);

вы бы увидели, что они отсортированы и получили ...

Array
(
    [3] => Array
        (
            [index] => 3
            [name] => AlexBrush
            [path] => assets/fonts/AlexBrush-Regular.ttf
        )

    [0] => Array
        (
            [index] => 0
            [name] => Arial
            [path] => assets/fonts/arial.ttf
        )

    [2] => Array
        (
            [index] => 2
            [name] => Roboto
            [path] => assets/fonts/roboto.ttf
        )

    [1] => Array
        (
            [index] => 1
            [name] => Times
            [path] => assets/fonts/times.ttf
        )

)

Или, как указал Л. Фарос в комментариях, если бы вы использовали ...

foreach ( $fonts as $font ) {
    echo "<br/>".$font["name"];
}

вы получите

<br/>AlexBrush<br/>Arial<br/>Roboto<br/>Times
...