3

I am trying to create a new array where the keys would be the headers from the first array and the values would be all other arrays but I am getting an empty array as a result.

Here is my initial array

$reader = \Asan\PHPExcel\Excel::load('test.xls', function(\Asan\PHPExcel\Reader\Xls $reader){});

foreach ($reader as $row)
{
    print_r($row);
}


Array
(
    [0] => Phone
    [1] => Sum
    [2] => Name
    [3] => Something else
)
Array
(
    [0] => +1 555123456
    [1] => 50.00
    [2] => Johnny Doe
    [3] => 100.50
)
Array
(
    [0] => 911
    [1] => 20.12
    [2] => Eli the Computer Guy
    [3] => 99.99
)

I tried to create the new array like this

$row = 1; // header row
foreach ($reader as $row)
{
    if ($row == 1)
    {
        $headers = $row;
    }
    else
    {
        $new_array[] = [
            $headers => $row;
        ]
    }

    print_r($row); // prints empty array
}

I would like the result array to look like this

Array
(
    [0] => Array
        (
            [Phone] => +1 555123456
            [Sum] => 50.00
            [Name] => Johnny Doe
            [Something else] => 100.50
        )

    [1] => Array
        (
            [Phone] => 911
            [Sum] => 20.12
            [Name] => Eli the Computer Guy
            [Something else] => 99.99
        )
)
Liga
  • 3,291
  • 5
  • 34
  • 59
  • Your trailing semi colon: `$headers => $row;` is a syntax error (it should be on the following line). And you want to be using an independent counter to $row that you increment or check against the array index. Your main problem here is that you are trying to add items to an array and are defining arrays like this: `[['name','sport'] => ['wilson', 'darts']]`, this doesn't work as you are hoping, and will result in an illegal offset error. See here: https://stackoverflow.com/a/10696097/3392762 – Progrock Nov 01 '18 at 09:23

3 Answers3

6

You can also use array_map and array_combine:

$headers = array_shift($arrays);
$result = array_map(function($x) use ($headers){
    return array_combine($headers, $x);
}, $arrays);

Demo

The fourth bird
  • 154,723
  • 16
  • 55
  • 70
  • 1
    Short and to the point. You don't really need the call to `array_values`. – Nick Nov 01 '18 at 08:11
  • 1
    It's a cleaner answer than mine, hence my upvote. My answer was more about explaining the issues with the original code. – Nick Nov 01 '18 at 08:17
3

You are overwriting your row counter $row with values from the reader: foreach ($reader as $row). You are also missing an increment on the row counter. Having fixed those issues, you can use array_combine to solve your problem:

$row = 1; // header row
$new_array = array();
foreach ($reader as $data)
{
    if ($row == 1)
    {
        $headers = $data;
    }
    else
    {
        $new_array[] = array_combine($headers, $data);
    }
    $row++;
}
print_r($new_array);

Demo on 3v4l.org

Nick
  • 138,499
  • 22
  • 57
  • 95
0

As Nick's answer but using the array key as a the conditional to check for the first array element (0 indexed).

<?php

$data = 
[
    ['shape', 'sides'],
    ['square', 4],
    ['triangle', 3]
];

foreach ($data as $key => $row) {
    if($key == 0) {
        $headers = $row;
    } else {
        $output[] = array_combine($headers, $row);
    }
}

var_export($output);

Output:

array (
    0 => 
    array (
    'shape' => 'square',
    'sides' => 4,
    ),
    1 => 
    array (
    'shape' => 'triangle',
    'sides' => 3,
    ),
)

The logic can be flipped a little to form a less readable one-liner:

foreach ($data as $key => $row)
    $key
    ? $output[] = array_combine($headers, $row)
    : $headers  = $row;

Usually array_shift is used to extract the headers row. You can then loop through your rows, without adding additional conditional clutter within your loops.

Progrock
  • 7,373
  • 1
  • 19
  • 25