Jump to content

Sort multidimensional array by value of release_date key


Recommended Posts

Posted

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.

Posted

@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
Posted
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
Posted

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
Posted

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
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...