MonkishTypist
MonkishTypist

Reputation: 13

How to group multidimensional array by sub-array value in and reassign keys in PHP

I looked at all the similar questions and samples (there are many) but still can't get this to work (though I think I am close).

I have an array of employee schedules pulled from a text file...

schedule.txt:


    123,Joe,20120208,0845,1645
    123,Joe,20120209,0800,1600
    456,Sue,20120208,0900,1700
    456,Sue,20120209,0700,1500
    ...

My code to generate the array is:


    $schedule = file_get_contents('./schedule.txt');
    $s = explode("\n", $schedule);
    for ($i = 0; $i < count($s); $i++) {
        $s[$i] = explode(",", $s[$i]);
    }
    print_r($s);

Output is:


    Array
    (
        [0] => Array
            (
                [0] => 123
                [1] => Joe
                [2] => 20120208
                [3] => 0845
                [4] => 1645
            )

        [1] => Array
            (
                [0] => 123
                [1] => Joe
                [2] => 20120209
                [3] => 0800
                [4] => 1600
            )

        [2] => Array
            (
                [0] => 456
                [1] => Sue
                [2] => 20120208
                [3] => 0900
                [4] => 1700
            )

        [3] => Array
            (
                [0] => 456
                [1] => Sue
                [2] => 20120209
                [3] => 0700
                [4] => 1500
            )
    )

I am instead trying to group employees by Id in a new multidimensional array with output like this:


    Array
    (
        [123] => Array
            (
                [0] => Array
                    (
                        [0] => Joe
                        [1] => 20120208
                        [2] => 0845
                        [3] => 1645
                    )

                [1] => Array
                    (
                        [0] => Joe
                        [1] => 20120209
                        [2] => 0800
                        [3] => 1600
                    )
            )

        [456] => Array
            (
                [0] => Array
                    (
                        [0] => Sue
                        [1] => 20120208
                        [2] => 0900
                        [3] => 1700
                    )

                [1] => Array
                    (
                        [0] => Sue
                        [1] => 20120209
                        [2] => 0700
                        [3] => 1500
                    )
            )
    )

I cannot for the life of me wrap my head around how to change my existing array into this new (different) output... I am trying this but getting nowhere:


    $newArr = array();

    foreach($s as $k => $v) {
        if(!isset($newArr[$v[0]])) {
            $newArr[$v[0]] = array();
        }

        $newArr[$v[0]][] = array($v[0]);
    }

Though my output is now:


    Array
    (
        [123] => Array
            (
                [0] => Array
                    (
                        [0] => 123
                    )

                [1] => Array
                    (
                        [0] => 123
                    )
            )

        [456] => Array
            (
                [0] => Array
                    (
                        [0] => 456
                    )

                [1] => Array
                    (
                        [0] => 456
                    )
            )
    )

Any thoughts? I know I am missing something in my code around the line:


    $newArr[$v[0]][] = array($v[0]);

I tried changing it to:


    $newArr[$v[0]][] = array(0 => $v[1], 1 => $v[2], 2 => $v[3], 3 => $v[4]);

which gives my the right output, but I now get undefined offset errors. Plus, if the number of keys in the sub array changes, this code is now limited to the 4 I explicitly entered...

Upvotes: 0

Views: 1660

Answers (4)

Levi Morrison
Levi Morrison

Reputation: 19552

There is a function called fgetcsv to easily grab comma separated values. No need to do it yourself.

This code also solves your problem and properly handles blank lines:

if (($handle = fopen("schedules.csv", "r")) !== FALSE) {

    $schedules = array();
    while (($data = fgetcsv($handle)) !== FALSE) {
        if ($data[0] !== null) { //blank lines return an array containing null
            $schedules[$data[0]][] = array_slice($data, 1);
        }
    }
    fclose($handle);

    //do what you need to

} else {
    // file failed to open
}

Note that I named the file .csv instead of .txt. I'd recommend that you save things that are comma separated values as .csv files. Maybe even define what each column is in the file as well.

Upvotes: 2

piouPiouM
piouPiouM

Reputation: 5037

You can use fscanf:

$handle    = fopen('./schedule.txt', 'r');
$employees = array();
while ($line = fscanf($handle, '%d,%s')) {
  $employees[$line[0]][] = explode(',', $line[1]);
}
fclose($handle);

print_r($employees);

Upvotes: 1

Jonathan Kuhn
Jonathan Kuhn

Reputation: 15301

<?php
//read the file into an array with each line being an entry
$schedule = file('./schedule.txt');
//empty array
$s = array();
//loop through file lines
foreach($schedule as $row){
    //explode on comma
    $row = explode(",", trim($row));
    //if the id doesn't exist yet...
    if(!isset($s[$row[0]])){
        //...make it an empty array
        $s[$row[0]] = array();
    }
    //add the row under the id
    $s[$row[0]][] = $row;
}
print_r($s);
?>

Upvotes: 1

boobiq
boobiq

Reputation: 3024

this should be enough, if I understood you right :)

$lines = file('./schedule.txt');

$employees = array();
foreach ($lines as $line)
{
    $chunks = explode(',', $line);
    $employees[$chunks[0]][] = array_slice($chunks, 1);
}

print_r($employees);

Upvotes: 4

Related Questions