0

I have a number of records like these:

2011-01-01, a, 1
2011-01-01, c, 5
2011-01-01, d, 3
2011-01-02, a, ...

The first value is a date, the second is a string (can be a or b or c or d), and the third is a number.

How can I add all the records into an array in PHP, and the array's structure is like:

array('2011-01-01' => array('a' => '1','b' => '0','c' => '5','d' => '3'), '2011-01-02' => ... ,)

so that the date variable is an index, and the key is a four-element array, each element is the corresponding record number (third value)?

2
  • How are initial records actually stored? As an array structure, in a file, or in a database? Commented Jan 10, 2012 at 0:13
  • read from database, stored as array Commented Jan 10, 2012 at 0:16

5 Answers 5

1

How about this (assuming the format of your input data):

$input = array(
    array('2011-01-01', 'a', '1'),
    array('2011-01-01', 'c', '5'),
    array('2011-01-01', 'd', '3'),
    array('2012-01-01', 'a', '1')
);

// used to populate the default strings (a b c d)
$strings = range('a', 'd');
$stringDefaults = array_combine($strings, array_fill(0, count($strings), '0'));

$output = array();

foreach ($input as $row) {
    list ($date, $string, $number) = $row;

    if (!isset($output[$date])) {
        $output[$date] = $stringDefaults;
    }

    $output[$date][$string] = $number;
}

echo json_encode($output);
Sign up to request clarification or add additional context in comments.

2 Comments

Won't that json_encode output the array with brackets not braces?
See codepad.org/7JIYcFhi; the arrays are associative so braces will be used. In any case, the JSON representation in the question seems only incidental to describing the structure, rather than the intended output, but I included it anyway.
1

Assuming this is a big string, split it on the lines, then on the commas. For each line, test if the date already exists as a key, and if it does, add to it, otherwise, create it:

$string = "2011-01-01, a, 1
2011-01-01, c, 5
2011-01-01, d, 3
2011-01-02, a, 1";

// Array to hold it all...
$array = array();
$lines = explode("\n", $string);
foreach ($lines as $line) {
  // Explode the line on the comma into 3 variables
  list($date, $key, $num) = explode(",", $line);
  $date = trim($date);
  $key = trim($key);
  $num = intval($num);

  // Create an array key for the current $date if it doesn't exist
  // as a new array
  if (!isset($array[$date])) $array[$date] = array();

  // And assign the number with the corresponding letter key to the array
  // for this date.
  $array[$date][$key] = $num;
}

1 Comment

I think this misses the requirement to have "b": "0" as part of the output (i.e. all possible strings a, b, c, d should show with a default number of 0)?
1
$records = array(
    0 => array('2011-01-01', 'a', '1'),
    1 => array('2011-01-01', 'c', '5'),
    2 => array('2011-01-01', 'd', '3'),
    3 => array('2012-01-01', 'a', '1')
);

$tmp_arr   = array();
$tmp_dates = array();
$tmp_str   = '';

foreach ($records as $record) {
    $tmp_arr[$record[0]][$record[1]] = $record[2];
}

foreach ($tmp_arr as $date => $record) {
    $tmp_params = array();
    foreach ($record as $key => $val) {
        $tmp_params[] = $key . ':' . $val;
    }
    $tmp_dates[] = $date . ':' . '{' . implode(',', $tmp_params) . '}';
}

$tmp_str = '{' . implode(',', $tmp_dates) . '}';

echo $tmp_str; // {2011-01-01:{a:1,c:5,d:3},2012-01-01:{a:1}}

1 Comment

As with Michael's answer, the OP seems to suggest each date array should be a 4-element array itself, with a default number of 0 if that line is not present in the input.
0

Provided your data is in a text file (.txt):

$records = file_get_contents("filename.txt");

// $records will be equal to the following: (on windows, it would be \r\n instead of just \n)
// $records = "2011-01-01, a, 1\n2011-01-01, c, 5\n2011-01-01, d, 3\n 2011-01-02, d, 3";

$records = explode("\n", $records);

$output = array();

for ($i = 0; $i < count($records); $i++) {

    $rec = explode(",", $records[$i]);
    $key = $rec[0];

    if ($output[$key] == null)
        $output[$key] = array();

    if (!array_key_exists("a", $output[$key]))
        $output[$key]["a"] = 0;

    if (!array_key_exists("b", $output[$key]))
        $output[$key]["b"] = 0;

    if (!array_key_exists("c", $output[$key]))
        $output[$key]["c"] = 0;

    if (!array_key_exists("d", $output[$key]))
        $output[$key]["d"] = 0;

    $elem = trim($rec[1]);
    $value = trim($rec[2]);
    $output[$key][$elem] = intval($value);

}

var_dump($output);

1 Comment

oh i just read in one of your comments that you are reading from the db and storing in an array, otherwise the format you posted initially looked like a text stream :) let me know if you have trouble translating above code to read from an array instead of a text file.
0

Ok, here's what you do.

$records = array(
    0 => array('2011-01-01', 'a', '1'),
    1 => array('2011-01-01', 'c', '5'),
    2 => array('2011-01-01', 'd', '3'),
    3 => array('2012-01-01', 'a', '1')
);

$dateArray = array();
$baseArray = array('a' => '0','b' => '0','c' => '0','d' = '0');

foreach($records as $record)
{
     $dateArray[$record[0]][$record[1]] = $record[2];  //You could actually do this while pulling in the info from the DB
}

foreach($dateArray as $date => $array)
{
     $missingArray = array_diff_key($array,$baseArray);  //Determine what keys are missing using the base array, get keys and default values
     $dateArray[$date] = array_merge($array,$missingArray);  //Merge the missing parts with the current array
}

Note, parts copied for time from other posts.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.