SamC

Sort multidimensional array by value of release_date key

Recommended Posts

Hi,

The array I'm working with (shortened example, the first three items) is:

Array
(
    [0] => Array
        (
            [character] => 
            [credit_id] => 5a26eac792514103360f3e03
            [release_date] => 2017-06-13
            [vote_count] => 5
            [video] => 
            [adult] => 
            [vote_average] => 7.6
            [title] => Celtics/Lakers: Best of Enemies
            [genre_ids] => Array
                (
                    [0] => 99
                )

            [original_language] => en
            [original_title] => Celtics/Lakers: Best of Enemies
            [popularity] => 3.191622
            [id] => 456788
            [backdrop_path] => 
            [overview] => A two-part series exploring the Celtics–Lakers rivalry, focusing mainly on the 1980s era of Larry Bird and Magic Johnson but also examining the entire history of the NBA through the rivalry.
            [poster_path] => /mF2ccs6AuGUvEIY9lfj8chFu6pW.jpg
        )

    [1] => Array
        (
            [character] => Performer
            [credit_id] => 5939ea8ec3a36823440029c4
            [release_date] => 2017-06-04
            [vote_count] => 1
            [video] => 
            [adult] => 
            [vote_average] => 1
            [title] => Comedy Central's Colossal Clusterfest
            [genre_ids] => Array
                (
                    [0] => 35
                )

            [original_language] => en
            [original_title] => Comedy Central's Colossal Clusterfest
            [popularity] => 1.651011
            [id] => 460340
            [backdrop_path] => /gsZT6wW4Oo7ApYD4TG5aZWby1Jj.jpg
            [overview] => Highlights from the inaugural Colossal Clusterfest that took place in San Francisco from June 2-4.
            [poster_path] => /ui1nZudYxcqJjFIZsiuTyqcV6PL.jpg
        )

    [2] => Array
        (
            [character] => 
            [credit_id] => 589119a092514103f000c00f
            [release_date] => 2017-03-10
            [vote_count] => 4
            [video] => 
            [adult] => 
            [vote_average] => 2.6
            [title] => G-Funk
            [genre_ids] => Array
                (
                    [0] => 99
                )

            [original_language] => en
            [original_title] => G-Funk
            [popularity] => 5.432522
            [id] => 438517
            [backdrop_path] => 
            [overview] => G-Funk is the untold story of three childhood friends from East Long Beach who helped commercialize hip hop by developing a sophisticated and melodic new approach – merging Gangsta Rap with elements of Motown, Funk, and R&B.
            [poster_path] => /lmByKQnHcMch8FkWzNquKtbFueN.jpg
        )
)

...and I wanted to sort them by date, newest first. It's small class like this. The problem is outlined in the comments:

<?php

namespace App\Controllers;

// Bring View class into current namespace
use \Core\View;
// Bring Actor model class into current namespace
use App\Models\Actor;

/**
 * About controller
 */
class Actors extends \Core\Controller {
  public function list() {

    // Model 'Actor' just queries API and returns array
    $movies = Actor::getAll();

    // Sort by date - newest first
    function sortNewestFirst( $a, $b ) {
      return strtotime($b["release_date"]) - strtotime($a["release_date"]);
    }
    /**
     * **********************************************
     * usort() ERRORS IF 'release_date' does not exist
     * **********************************************
     */
    usort($movies, "App\Controllers\sortNewestFirst");

    View::renderTemplate('Actor/listAll.html', [
      'name' => $this->getFormattedName(),
      'movies' => $movies
      ]
    );
  }

  /**
   * Get the current name from URL
   */
  private function getFormattedName() {
    return ucwords(htmlspecialchars($_GET['name'], ENT_QUOTES | ENT_SUBSTITUTE, "UTF-8"));
  }
}

The error:

Uncaught exception: 'ErrorException'
Message: 'Undefined index: release_date'

Unfortunately, the API has no release date for some movies, so my search works perfectly for some actors, but errors for others. I was trying to figure out how to get array_key_exists() into this somehow but I'm totally stuck. Being an array of arrays makes this more tricky. I was thinking of looping each one, if the key exists, add to a new array, but then the movie with the missing key would be completely absent. I was thinking of just chucking it at the bottom of the list.

Hopefully this makes sense. Any help, hints or improvements would be awesome, thanks.

Share this post


Link to post
Share on other sites

You could use array_filter to create two arrays: one with and one without release dates. Sort the first one and append the second one.

  • Thanks 1

Share this post


Link to post
Share on other sites

@SamC,

Moderator Note

FYI, you posted 3 other copies of this thread. I am guessing you were on mobile, or your computer was a bit wonky. I've deleted the other three.

  • Thanks 1

Share this post


Link to post
Share on other sites
56 minutes ago, arjen said:

You could use array_filter to create two arrays: one with and one without release dates. Sort the first one and append the second one.

I'll give this a try, thanks.

25 minutes ago, kongondo said:

@SamC,

Moderator Note

FYI, you posted 3 other copies of this thread. I am guessing you were on mobile, or your computer was a bit wonky. I've deleted the other three.

Thanks, had a problem submitting, 2mins+ with nothing haopening so I refreshed, waited, waited, redreshed, tried again. Third time submitted normally i.e. took seconds. Not sure what went wrong, maybe dodgy internet.

  • Like 1

Share this post


Link to post
Share on other sites

Did this now, code could most likely be improved, but it works:

if ($movies) {

  // Movies with release date
  function hasReleaseDate($movies) {
    return (array_key_exists('release_date', $movies)) ? true : false;
  }

  // Movies without release date
  function noReleaseDate($movies) {
    return (!array_key_exists('release_date', $movies)) ? true : false;
  }

  // Generate arrays of movies with/without release date
  $movies_with_release_date = array_filter($movies, 'App\Controllers\hasReleaseDate');
  $movies_without_release_date = array_filter($movies, 'App\Controllers\noReleaseDate');

  // Sort by date - newest first
  function sortNewestFirst( $a, $b ) {
    return strtotime($b["release_date"]) - strtotime($a["release_date"]);
  }
  usort($movies_with_release_date, "App\Controllers\sortNewestFirst");

  // Append movies without release date
  $movies = array_merge($movies_with_release_date, $movies_without_release_date);

  View::renderTemplate('Actor/list-all.html', [
    'name' => $this->getFormattedName($name),
    'movies' => $movies
    ]
  );
}
else {
  View::renderTemplate('Actor/no-results.html');     
}

The more I move on with this, the more I see the importance of finding some kind of  structure. It's starting to confuse myself with where to put code, whether it goes in a model, a controller etc. Def need to work on this.

However, all good for now :) thanks @arjen

  • Like 1

Share this post


Link to post
Share on other sites

Only just noticed the release_date key is either not there at all, or present, but empty for some movies e.g.:

[97] => Array
    (
        [character] => Fred Rogers
        [credit_id] => 5a709346c3a36847e4012aaa
        [poster_path] => 
        [id] => 501907
        [video] => 
        [vote_count] => 0
        [adult] => 
        [backdrop_path] => 
        [genre_ids] => Array
            (
                [0] => 18
            )

        [original_language] => en
        [original_title] => You Are My Friend
        [popularity] => 1
        [title] => You Are My Friend
        [vote_average] => 0
        [overview] => The story of Fred Rogers, the honored host and creator of the popular children's television program, Mister Rogers' Neighborhood (1968).
        [release_date] =>
    )

Had to modify the  functions as checking for key existence was not enough:

// Movies with release date
function hasReleaseDate($movie) {
  // Has key with value
  if (array_key_exists('release_date', $movie) && !empty($movie['release_date'])) {
    return true;
  }
  return false;
}

// Movies without release date
function noReleaseDate($movie) {
  // No key
  if (!array_key_exists('release_date', $movie)) {
    return true;
  }
  // Has key but no value
  if (array_key_exists('release_date', $movie) && empty($movie['release_date'])) {
    return true;
  }
  return false;
}

Seems to work now.

  • Like 1

Share this post


Link to post
Share on other sites

  • Recently Browsing   0 members

    No registered users viewing this page.