1

I have an array containing possible values:

$auto_types = array(CHEVY, FORD, DODGE);

And I have have arrays that contain those values:

$my_cars = array(
  array("make" => "FORD", model => "Thunderbird", "year" => 1983),
  array("make" => "FORD", model => "Mustang", "year" => 1971),
  array("make" => "CHEVY", model => "Impala", "year" => 1995),
  array("make" => "DODGE", model => "Charger", "year" => 2015),
  array("make" => "CHEVY", model => "Corvette", "year" => 2011),
  array("make" => "CHEVY", model => "Camaro", "year" => 2012)
)

I want to return a list that supplies a header of each make, and then sorts each car by the Make. So the output would be:

CHEVY:
1995 Impala
2012 Corvette
2011 Camaro

DODGE:
2015 Charger

FORD:
1971 Mustang
1983 Thunderbird

I know I can run a foreach() loop and sort by make, but the key here is that I want a header for each make, instead of listing it for every car. Anyone have a good way to do this? -- Not sure if the first array is even needed, but it seemed like a good idea to create it at the time.

dougblitz210
  • 139
  • 2
  • 9
  • Possible duplicate of [How to sort an array of associative arrays by value of a given key in PHP?](http://stackoverflow.com/questions/1597736/how-to-sort-an-array-of-associative-arrays-by-value-of-a-given-key-in-php) – Nehal J Wani Aug 15 '16 at 19:40
  • 1
    He's specifically asking how to **print a header** for each make, before the maker's cars are listed. I understand he already has an idea of how to sort them. – Markus AO Aug 15 '16 at 19:54

4 Answers4

3

First you'll want to sort the array by make. You can do that with the help of array_multisort().

When you loop through your array for your list output, you can keep a variable that stores the make of the previous car. Then, whenever there's a new make, just print a header before the car's entry.

$ex_make = '';

foreach($my_cars as $car) {
    ...
    if ($car['make'] != $ex_make) {
        print_header($car['make']);
    }
    ...
    $ex_make = $car['make'];
}

You can make your life easier by grouping your cars by make into a multidimensional array. It'll spare you from the sorting process (and the grouping loops suggested in other answers). If you have lots more cars coming in, you'll want to consider using a database instead.

Markus AO
  • 4,771
  • 2
  • 18
  • 29
  • Simple and effective. Greatly appreciated, Thanks! – dougblitz210 Aug 15 '16 at 20:52
  • Welcome. I was quite humored with the elaborate answers that missed the point of *"wants to print that header"*. If you care to group your car'rrays by make, whether with one of those loops, or by modifying your source data (which would make more sense to me), then obviously you could print your header in the beginning of each main loop (iterating the make-level of your array). But simple is nice. ;) – Markus AO Aug 15 '16 at 21:10
  • Yeah, source data is actually coming from a CMS which is going to make editing the source problematic, so I just wanted to make a simple example that properly illustrated my issue. – dougblitz210 Aug 15 '16 at 21:16
  • If it's coming from a database, why not `ORDER` by `make` first and spare PHP the trouble. If you had them grouped as `$my_cars['FORD'][] = ["model" => "Thunderbird", "year" => 1983];` etc., you could simply `foreach($my_cars as $make=>$cars) { echo $make."
    "; array_walk($cars, function($car) { echo "{$car['year']} {$car['model']}
    "; }); }` (untested)
    – Markus AO Aug 15 '16 at 21:21
  • Two words, Drupal Views :) ... still gonna play with this a bit to see if I can come up with something better. But I greatly appreciate your help! – dougblitz210 Aug 16 '16 at 14:15
1

You don't need the first array. You can use one loop to group the cars by make:

foreach ($my_cars as $car) {
    $makes[$car['make']][] = $car;
}

If you want the makes to appear in alphabetical order, then you can ksort($makes).

Then loop over the makes and print the cars for each one.

foreach ($makes as $make => $cars) {
    echo "$make: ";                       // Header prints once
    foreach ($cars as $car) {
        echo "$car[model] $car[year] ";   // Multiple cars print after each header
    }
    echo '<br>';
}
Don't Panic
  • 41,125
  • 10
  • 61
  • 80
0
<?php

$my_cars = array(
  array("make" => "FORD", "model" => "Thunderbird", "year" => 1983),
  array("make" => "FORD", "model" => "Mustang", "year" => 1971),
  array("make" => "CHEVY", "model" => "Impala", "year" => 1995),
  array("make" => "DODGE", "model" => "Charger", "year" => 2015),
  array("make" => "CHEVY", "model" => "Corvette", "year" => 2011),
  array("make" => "CHEVY", "model" => "Camaro", "year" => 2012)
);

// defining empty arrays for each models
$ford = [];
$chevy = [];
$dodge = [];

// loop through every car and push to the right array model
foreach($my_cars as $array) {
  if($array['make'] == "FORD") {
    array_push($ford, $array);
  } elseif($array['make'] == "CHEVY") {
    array_push($chevy, $array);
  } else {
    array_push($dodge, $array);
  }
}

// echo the result by looping inside each array model
foreach($dodge as $car) {
  echo $car['year'] . ':' . $car['model'] . '<br />';
}

echo '<br />';

foreach($ford as $car) {
  echo $car['year'] . ':' . $car['model'] . '<br />';
}

echo '<br />';

foreach($chevy as $car) {
  echo $car['year'] . ':' . $car['model'] . '<br />';
}
Ivan
  • 34,531
  • 8
  • 55
  • 100
-1

Nested Loop would be ideal here.

    <?php
        $auto_types = array("CHEVY", "FORD", "DODGE");
        $my_cars    = array(
            array("make" => "FORD",  "model" => "Thunderbird",  "year" => 1983),
            array("make" => "FORD",  "model" => "Mustang",      "year" => 1971),
            array("make" => "CHEVY", "model" => "Impala",       "year" => 1995),
            array("make" => "DODGE", "model" => "Charger",      "year" => 2015),
            array("make" => "CHEVY", "model" => "Corvette",     "year" => 2011),
            array("make" => "CHEVY", "model" => "Camaro",       "year" => 2012)
        );

        $arr = [];
        foreach($my_cars as $my_car){
            foreach($auto_types as $auto_type){
                if($make = array_search($auto_type, $my_car)){
                    $desc   = $my_car['make'] . " " . $my_car['year'] . " " . $my_car['model'];
                    if(!array_key_exists($auto_type, $arr)){
                        $arr[$auto_type] = $desc;
                    }else{
                        $arr[$auto_type] = $arr[$auto_type] .  "    " . $my_car['year'] . " " . $my_car['model'] . "";
                    }
                }
            }
        }
        ksort($arr);

        var_dump ($arr);
        // PRODUCES::           
        array (size=3)
          'CHEVY' => string 'CHEVY 1995 Impala    2011 Corvette    2012 Camaro' (length=49)
          'DODGE' => string 'DODGE 2015 Charger' (length=18)
          'FORD' => string 'FORD 1983 Thunderbird    1971 Mustang' (length=37)

        $output = implode("<br />", $arr);
        echo $output;

        // PRODUCES::
        CHEVY 1995 Impala 2011 Corvette 2012 Camaro
        DODGE 2015 Charger
        FORD 1983 Thunderbird 1971 Mustang

EFFECTIVE CODE

    <?php
        $arr = [];
        foreach($my_cars as $my_car){
            foreach($auto_types as $auto_type){
                if($make = array_search($auto_type, $my_car)){
                    $desc   = $my_car['make'] . " " . $my_car['year'] . " " . $my_car['model'];
                    if(!array_key_exists($auto_type, $arr)){
                        $arr[$auto_type] = $desc;
                    }else{
                        $arr[$auto_type] = $arr[$auto_type] .  "    " . $my_car['year'] . " " . $my_car['model'] . "";
                    }
                }
            }
        }
        ksort($arr);
        $output = implode("<br />", $arr);  //<== GET STRING VALUE...
        echo $output;
Poiz
  • 7,611
  • 2
  • 15
  • 17