php - Group array row data by two columns creating a new 3-level structure

705

I have 1 arrays:

array(5) { // This is the keys on the CSV.
  [0]=>
  array(4) {
    [0]=>
    string(4) "user"
    [1]=>
    string(4) "date"
    [2]=>
    string(3) "md5"
    [3]=>
    string(4) "sha1"
  }
  [1]=>
  array(4) {
    [0]=>
    string(4) "user1"
    [1]=>
    string(8) "02/02/15"
    [2]=>
    string(6) "123456"
    [3]=>
    string(5) "54321"
  }
  [2]=>
  array(4) {
    [0]=>
    string(4) "user1"
    [1]=>
    string(8) "02/03/15"
    [2]=>
    string(6) "123456"
    [3]=>
    string(5) "54321"
  }
  [3]=>
  array(4) {
    [0]=>
    string(5) "user2"
    [1]=>
    string(8) "02/02/15"
    [2]=>
    string(6) "112233"
    [3]=>
    string(6) "332211"
  }
  [4]=>
  array(4) {
    [0]=>
    string(5) "user2"
    [1]=>
    string(8) "02/03/15"
    [2]=>
    string(6) "112244"
    [3]=>
    string(6) "332244"
  }
}

So User 1 and User 2 each have a file that is MD5/SHA1 sum'd and checked.

I would like the data to turn from the above, to this:

array(3) {
  ["user"]=>
  array(1) {
    ["date"]=>
    array(2) {
      [0]=>
      string(3) "md5"
      [1]=>
      string(4) "sha1"
    }
  }
  ["user1"]=>
  array(1) {
    ["02/02/15"]=>
    array(2) {
      [0]=>
      string(6) "123456"
      [1]=>
      string(5) "54321"
    }
    ["02/03/15"]=>
    array(2) {
      [0]=>
      string(6) "123456"
      [1]=>
      string(5) "54321"
    }
  }
  ["user2"]=>
  array(1) {
    ["02/02/15"]=>
    array(2) {
      [0]=>
      string(6) "112233"
      [1]=>
      string(6) "332211"
    }
    ["02/03/15"]=>
    array(2) {
      [0]=>
      string(6) "112244"
      [1]=>
      string(6) "332244"
    }
  }
}

So far, I'm close. Here is my code:

<?php
error_reporting(E_ALL & ~E_NOTICE);

//Reading csv

$csv = array_map('str_getcsv',file('/var/www/sums.csv'));

debug($csv);
//User list
$userData = array();

foreach ($csv as $user) {
        $ts = $user[1];
        $un = $user[0];
        $sums = array($user[2],$user[3]);
        $userPreProc[$un] = array($ts => $sums);
        $userData = array_merge($userPreProc, $userData);
}

debug($userData);

function debug($db) {
        echo "<pre>";
        var_dump($db);
        echo "</pre>";
}
?>

The issue here is that only the first 'user1' and 'user2' entries are merged to the new array, so it looks like this:

array(3) {
  ["user"]=>
  array(1) {
    ["date"]=>
    array(2) {
      [0]=>
      string(3) "md5"
      [1]=>
      string(4) "sha1"
    }
  }
  ["user1"]=>
  array(1) {
    ["02/02/15"]=>
    array(2) {
      [0]=>
      string(6) "123456"
      [1]=>
      string(5) "54321"
    }
  }
  ["user2"]=>
  array(1) {
    ["02/02/15"]=>
    array(2) {
      [0]=>
      string(6) "112233"
      [1]=>
      string(6) "332211"
    }
  }
}

Any suggestions how I can ensure that all the keys are merged as expected?

592

Answer

Solution:

Just shift off the first two elements and use those respective values as the first and second level keys.

Code: (Demo)

$result = [];
foreach ($array as $row) {
    $result[array_shift($row)][array_shift($row)] = $row;
}
var_export($result);

Or use array destructuring in the foreach declaration: (Demo)

$result = [];
foreach ($array as [$user, $date, $md5, $sha1]) {
    $result[$user][$date] = [$md5, $sha1];
}
var_export($result);
126

Answer

Solution:

Just change your foreach loop to be like this. You don't need to merge your array via function.

foreach ($csv as $user) {
        $ts = $user[1];
        $un = $user[0];
        $sums = array($user[2],$user[3]);
        $userData[$un][$ts] = $sums;
}

People are also looking for solutions to the problem: PHP fileatime -> Always 1 o'clock in the morning

Source

Didn't find the answer?

Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.

Ask a Question

Write quick answer

Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.

Similar questions

Find the answer in similar questions on our website.