String manipulation required to get exact values in array

I have following dynamic output available upon accessing sms gateway provider api for delivery report:

919550272832 | 1| id:1187093564 sub:001 dlvrd:001 submit date:1312191022 done date:1312191022 stat:DELIVRD err:000 text: | 2013-12-19 10:22:59
919551370177 | 1| id:1170330677 sub:001 dlvrd:001 submit date:1312191022 done date:1312191022 stat:DELIVRD err:000 text: | 2013-12-19 10:22:59
918558840953 | 1| id:1187093566 sub:001 dlvrd:001 submit date:1312191022 done date:1312191022 stat:DELIVRD err:000 text: | 2013-12-19 10:22:59
918558851999 | 2| id:1170330676 sub:001 dlvrd:001 submit date:1312191022 done date:1312191242 stat:UNDELIV err:027 text: | 2013-12-19 12:42:59
919552673202 | 2| id:1136761922 sub:001 dlvrd:001 submit date:1312191022 done date:1312191242 stat:UNDELIV err:027 text: | 2013-12-19 12:42:59

Now I need to convert above string to an array which should look like as follows:

Array
    (
       [919550272832] => Array
         (
            [id] => 1187093564
            [sub] => 001
            [dlvrd] => 001
            [date] => 1312191022
            [stat] => DELIVRD
            [err] => 000
          )
        [918558851999] => Array
          (
            [id] => 1170330677
            [sub] => 001
            [dlvrd] => 001
            [date] => 1312191022
            [stat] => UNDELIV
            [err] => 027
            )
    )

key:value format in an array.

i have intentionally removed some of values from original output to make array look better, but i have no problem if those values becomes part of final array output.

Can anyone help me with some clue or some reference?

Thank you

Answers


Here's a working example:

// load lines from a file
$lines = array(
    '919550272832 | 1| id:1187093564 sub:001 dlvrd:001 submit date:1312191022 done date:1312191022 stat:DELIVRD err:000 text: | 2013-12-19 10:22:59',
    '919551370177 | 1| id:1170330677 sub:001 dlvrd:001 submit date:1312191022 done date:1312191022 stat:DELIVRD err:000 text: | 2013-12-19 10:22:59',
    '918558840953 | 1| id:1187093566 sub:001 dlvrd:001 submit date:1312191022 done date:1312191022 stat:DELIVRD err:000 text: | 2013-12-19 10:22:59',
    '918558851999 | 2| id:1170330676 sub:001 dlvrd:001 submit date:1312191022 done date:1312191242 stat:UNDELIV err:027 text: | 2013-12-19 12:42:59',
    '919552673202 | 2| id:1136761922 sub:001 dlvrd:001 submit date:1312191022 done date:1312191242 stat:UNDELIV err:027 text: | 2013-12-19 12:42:59',
);

// or 
$lines = file_get_contents('myfile.txt');

$output = array();

// process each line    
foreach ($lines as $line) {
    // split parts by the pipe (|) and trim each entry
    $data = explode('|', $line);
    $data = array_map('trim', $data);

    // extract each part to a separate variable
    list($isbn, $i, $params, $date) = $data;

    // extract all colon-separated parameters from the third part
    preg_match_all('/(?P<key>[a-z]+):(?P<value>[a-z0-9]+)/i', $params, $matches);

    // add each parameter to the output array 
    for ($i = 0; $i < count($matches['key']); $i++) {
        $key   = $matches['key'][$i];
        $value = $matches['value'][$i];
        $output[$isbn][$key] = $value;
    }
}

The resulting $output is as follows:

array(5) {
  [919550272832]=>
  array(6) {
    ["id"]=>
    string(10) "1187093564"
    ["sub"]=>
    string(3) "001"
    ["dlvrd"]=>
    string(3) "001"
    ["date"]=>
    string(10) "1312191022"
    ["stat"]=>
    string(7) "DELIVRD"
    ["err"]=>
    string(3) "000"
  }
  [919551370177]=>
  array(6) {
    ["id"]=>
    string(10) "1170330677"
    ["sub"]=>
    string(3) "001"
    ["dlvrd"]=>
    string(3) "001"
    ["date"]=>
    string(10) "1312191022"
    ["stat"]=>
    string(7) "DELIVRD"
    ["err"]=>
    string(3) "000"
  }
  [918558840953]=>
  array(6) {
    ["id"]=>
    string(10) "1187093566"
    ["sub"]=>
    string(3) "001"
    ["dlvrd"]=>
    string(3) "001"
    ["date"]=>
    string(10) "1312191022"
    ["stat"]=>
    string(7) "DELIVRD"
    ["err"]=>
    string(3) "000"
  }
  [918558851999]=>
  array(6) {
    ["id"]=>
    string(10) "1170330676"
    ["sub"]=>
    string(3) "001"
    ["dlvrd"]=>
    string(3) "001"
    ["date"]=>
    string(10) "1312191242"
    ["stat"]=>
    string(7) "UNDELIV"
    ["err"]=>
    string(3) "027"
  }
  [919552673202]=>
  array(6) {
    ["id"]=>
    string(10) "1136761922"
    ["sub"]=>
    string(3) "001"
    ["dlvrd"]=>
    string(3) "001"
    ["date"]=>
    string(10) "1312191242"
    ["stat"]=>
    string(7) "UNDELIV"
    ["err"]=>
    string(3) "027"
  }
}

Hope that helps!


If your output of the SMS service will always be like this (assuming the information you need will always be a key value pair split by :, then you can technically do it this way. This is super generic so make sure you edit out things you don't need.

$text = '919550272832 | 1| id:1187093564 sub:001 dlvrd:001 submit date:1312191022 done date:1312191022 stat:DELIVRD err:000 text: | 2013-12-19 10:22:59
    919551370177 | 1| id:1170330677 sub:001 dlvrd:001 submit date:1312191022 done date:1312191022 stat:DELIVRD err:000 text: | 2013-12-19 10:22:59
    918558840953 | 1| id:1187093566 sub:001 dlvrd:001 submit date:1312191022 done date:1312191022 stat:DELIVRD err:000 text: | 2013-12-19 10:22:59
    918558851999 | 2| id:1170330676 sub:001 dlvrd:001 submit date:1312191022 done date:1312191242 stat:UNDELIV err:027 text: | 2013-12-19 12:42:59
    919552673202 | 2| id:1136761922 sub:001 dlvrd:001 submit date:1312191022 done date:1312191242 stat:UNDELIV err:027 text: | 2013-12-19 12:42:59';

$lines = explode("\r\n", $text);
foreach($lines as $line){
    $keyVals = explode(" ", $line);
    $output = array();
    foreach($keyVals as $pair){
        $temp = explode(":", $pair);
        if(array_key_exists('1', $temp)){
            $output[$temp[0]] = $temp[1];
        }
    }
    print_r($output);
}

Output:

Array
(
    [id] => 1187093564
    [sub] => 001
    [dlvrd] => 001
    [date] => 1312191022
    [stat] => DELIVRD
    [err] => 000
    [text] =>
    [10] => 22
)

I think the best way to resolve this is using preg_match function


This looks like a job for... regular expressions!

You can simply use a regex to pull out the values after each of the titles:

/^(\d*) \| \d\| id:(\d*) sub:(\d*) dlvrd:(\d*) submit date:(\d*) done date:(\d*) stat:(\w*) err:(\d*) text: \| (.*)$/m

Use preg_match_all for this:

$regex = '/^(\d*) \| \d\| id:(\d*) sub:(\d*) dlvrd:(\d*) submit date:(\d*) done date:(\d*) stat:(\w*) err:(\d*) text: \| (.*)$/m';

$ret = array();
if(preg_match_all($regex, $data, $matches, PREG_SET_ORDER) > 0){
    foreach($matches as $val){
        $ret[$val[1]] = array(
            'id' => $val[2],
            'sub' => $val[3],
            'dlvrd' => $val[4],
            'date' => $val[5],
            'stat' => $val[7],
            'err' => $val[8]
        );
    }
}

DEMO: https://eval.in/88656


Well you can do it like this tho, not really the best example.

$lines = array(
    '919550272832 | 1| id:1187093564 sub:001 dlvrd:001 submit date:1312191022 done date:1312191022 stat:DELIVRD err:000 text: | 2013-12-19 10:22:59',
    '919551370177 | 1| id:1170330677 sub:001 dlvrd:001 submit date:1312191022 done date:1312191022 stat:DELIVRD err:000 text: | 2013-12-19 10:22:59',
    '918558840953 | 1| id:1187093566 sub:001 dlvrd:001 submit date:1312191022 done date:1312191022 stat:DELIVRD err:000 text: | 2013-12-19 10:22:59',
    '918558851999 | 2| id:1170330676 sub:001 dlvrd:001 submit date:1312191022 done date:1312191242 stat:UNDELIV err:027 text: | 2013-12-19 12:42:59',
    '919552673202 | 2| id:1136761922 sub:001 dlvrd:001 submit date:1312191022 done date:1312191242 stat:UNDELIV err:027 text: | 2013-12-19 12:42:59',
);

$keys = array(
    'id','sub','dlvrd', 'date', 'stat', 'err'
);

// Create array with key
$newArray = array();

foreach($lines as $string){
    // get the key for our new array. ex: 919550272832  (12 digits regex)
    $key = preg_match('/\d{12}/', $string, $match);
    $key = current($match);

    $newArray[$key] = array();

    foreach($keys as $k => $v){
           // regex prefix till space
           if(preg_match('/'.$v.':(.*?)\s+/', $string, $match))
                $newArray[$key][$v] = $match[1];
     }


}

echo '<pre>';
print_r($newArray);

Need Your Help

Reading the whole text file into a char array in C

c text file-io

I want to read the contents of a text file into a char array in C. Newlines must be kept.