Вывод массива php в определенном формате

есть массив данных условной библиотеки:

    $data = [
    'authors' => [
        301 => [
            'id' => 301,
            'name' => 'Александр Сергеевич Пушкин',
            'email' => '[email protected]',
            'birthYear' => 1799,
        ],
        10 => [
            'id' => 10,
            'name' => 'Николай Васильевич Гоголь',
            'email' => '[email protected]',
            'birthYear' => 1809,
        ],
        17 => [
            'id' => 17,
            'name' => 'Михаил Юрьевич Лермонтов',
            'email' => '[email protected]',
            'birthYear' => 1814,
        ],
    ],
    'books' => [
        [
            'title' => 'Евгений Онегин',
            'publishedAt' => '1823—1832',
            'author' => 301,
        ],
        [
            'title' => 'Полтава',
            'publishedAt' => '1828—1829',
            'author' => 301,
        ],
        [
            'title' => 'Мёртвые души',
            'publishedAt' => '1842',
            'author' => 10,
        ],
        [
            'title' => 'Сказка о рыбаке и рыбке',
            'publishedAt' => '1833',
            'author' => 301,

        ],
    ],
];

Необходимо вывести в формате:

=== Авторы ===

Николай Васильевич Гоголь – [email protected] - 1809

Александр Сергеевич Пушкин – [email protected] - 1799

=== Книги ===

Мертвые души – Николай Васильевич Гоголь - 1841

Пиковая дама - Александр Сергеевич Пушкин - 1833

Для вывода я написал следующий код:

   echo '=== Авторы ===<br>';
    array_map(function($data){
        echo sprintf('%s – %s – %s',$data['name'], $data['email'], $data['birthYear']) . '<br>';
    }, $data['authors']);
    
    echo '=== Книги ===<br>';
    array_map(function($data){
        echo sprintf('%s – %s – %s',$data['title'], $data['author'], $data['publishedAt']) . '<br>';
    }, $data['books']);

Но проблема в том, что таким образом выводится именно ID автора указанный в 'books'. А мне нужен вывод полного имени автора, который указан в 'authors'. Можете, пожалуйста, подсказать или направить как это можно реализовать?


Ответы (2 шт):

Автор решения: teran
  • array_map() используют для преобразования данных. вы же ничего не модифицируете и не возвращаете. С этой целью, если и использовать подобные функции, то array_walk(). Хотя вывод кода внутри функций - так себе затея.
  • sprintf наиболее медленное решение для генерации строки из всех возможных. медленней чем конкатенация и тем более чем подстановка переменных в строку.
  • чтобы получить данные автора, необходимо сделать весь массив data доступным внутри функции. Для сего можно использовать use ($data) но локальный параметр переименовать в какое-нибудь $v.
  • тогда $aId = $v['author_id'] и данные автор доступны через $name = $data[$aId]['name']. Поскольку ключами массива авторов являются их идентификаторы, то никакие циклы тут не нужны.
  • вывод организовать через "{$v['title']} - {$name}\n" и т.п.
→ Ссылка
Автор решения: endyrlx

Встретил это задание в тесте при отборе на стажировку в qsoft. Добавлю, что условиями задачи было запрещено использование функций и сторонних переменных. Сначала тоже пытался выполнить задание через sprintf, но не получилось сопоставить id автора из books с именем автора по id в authors. В результате многочасовых мучений, внезапно, нашлось очень простое решение (возможно, костыль, но работает + было принято в качестве ответа)

/* ===== Ваш код ниже ===== */

echo '=== Авторы ===<br>';
// Ваш код здесь
foreach ($data['authors'] as $key => $value) {
        echo "$value[name] – $value[email] – $value[birthYear] <br>";
}

echo '=== Книги ===<br>';
foreach ($data['authors'] as $key => $value) {
    foreach ($data['books'] as $kkey => $vvalue) {
        if ($vvalue['author'] == $value['id']) {
            echo "$vvalue[title] – $value[name] – $vvalue[publishedAt] <br>";
        }
    }
}
→ Ссылка