kirchner20
kirchner20

Reputation: 97

Parse lines of nearly-csv text into a multidimensional array with 3 levels

I have an array containing data separated by a comma:

array (
    [0] => Jack,140101d,10
    [1] => Jack,140101a,15
    [2] => Jack,140101n,20
    [3] => Jane,141212d,20
    [4] => Jane,141212a,25
    [5] => Jane,141212n,30
)

There is a lot of data and I would like the data to be set out as:

array(
      [Jack]=>
          [140101] =>
              [d] => 10
              [a] => 15
              [n] => 20
      )
      ...

My code:

foreach ($out as $datavalue) {
    $dat = str_getcsv($datavalue, ',');
    $datevalue = substr($dat[1], 2, -1);
    $shiftvalue = substr($dat[1], -1);
    $totalvalue = $dat[2];
    $sval[$shiftvalue] = $totalvalue;
    $dval[$datevalue] = $sval;
    $opvalue = $dat[0];
    $final[$opvalue] = $dval;
}

Now it seems the array is populated even if there is no data from the original string, so my output shows results for Jack on the other dates even though there was no data for him originally.

Upvotes: 1

Views: 106

Answers (2)

mickmackusa
mickmackusa

Reputation: 48071

If you need to accommodate csv text that might have escaped double quotes in it, then dedicated csv parsing functions are ideal. Considering your sample input, it seems that you data is more simply parsed with sscanf().

  • The first level key comes from the first non-comma characters.
  • The second level key comes from the 6-digit number after the first comma.
  • The third level key comes from the letter following the number.
  • The third level value comes from the number after the second comma.

Array destructuring syntax allows you to declare those keys and immediately use them to build the path for the third level value. Demo

$result = [];
foreach ($array as $v) {
    [$name, $date, $shift, $result[$name][$date][$shift]] = sscanf($v, '%[^,],%6d%1s,%d');
}
var_export($result);

Upvotes: 0

Andresch Serj
Andresch Serj

Reputation: 37468

As mentioned in the comments, explode is what you need. See this working here.

<?php

$input = array (
  0 => 'Jack,140101d,10',
  1 => 'Jack,140101a,15',
  2 => 'Jack,140101n,20',
  3 => 'Jane,141212d,20',
  4 => 'Jane,141212a,25',
  5 => 'Jane,141212n,30',
);

$result = array();

foreach ($input as $key => $value) {
  $valueParts = explode(',',$value); // now valueparts is an array like ('Jack','140101d','10')
  $namePart     = $valueParts[0];
  $idPart   = substr($valueParts[1],0,-1); // we need to strip the letter from the id
  $charPart     = substr($valueParts[1],-1); // and the id from the letter
  $nrPart   = $valueParts[2]; // you could use intval() to make this an integer rather than a string if you want

  // Now we fill the array
  if(!array_key_exists($namePart, $result)) {
    $result[$namePart] = array();
  }
  if(!array_key_exists($idPart, $result[$namePart])) {
    $result[$namePart][$idPart] = array();
  }
  if(!array_key_exists($charPart, $result[$namePart][$idPart])) {
    $result[$namePart][$idPart][$charPart] = $nrPart;
  }
}

var_dump($result);

Upvotes: 1

Related Questions