Home > Back-end >  Parsing input text to array and sum values
Parsing input text to array and sum values

Time:11-01

Hello :) I am stuck in my mini-app developing. I have following text, copied from 3rd party web page:

Type A    GZ 600    11.09.2021 12:00        OST    9
Type A    GZ 601    11.09.2021 13:20        ADS    1
Type A    GZ 602    11.09.2021 21:35        OCS    1
Type A    GZ 603    11.09.2021 14:50        CSE    10
Type B    GZ 600    11.09.2021 12:00        OST    5
Type B    GZ 601    11.09.2021 13:20        ADS    3
Type B    GZ 602    11.09.2021 21:35        OCS    6
Type B    GZ 603    11.09.2021 14:50        CSE    12

I need to parse it to following format: $s = 10, $ns = 11, $bs = 26, like:

echo "S:" . $s . " NS:" . $ns . " BS:" . $bs; // Output: S:10 NS:11 BS:26

where:
$fa = array("OCS", "CSE"); is array of codes
$ns is sum of Type A last column numbers, which 5 column 3-letter code is in the array, 
$s is sum of Type A last column numbers, which 5 column 3-letter code is not in the array
$bs is just sum of Type B last column numbers

My code now is following:

if(!empty($_POST['indata'])){
  $in_data = $_POST['indata'];                // Get POST data
  $fa = array("OCS", "CSE");                  // Make array
  $ns = 0;                                    // Init ns value
  $s = 0;                                  // Init ss value
  foreach(explode("/n",$in_data) as $line){   // Divide text to lines
    $info[] = explode("    ", $line);         // Divide line to values and put them to array 
    print_r($info);  //Show input for test purposes                         
    if(in_array($info[4], $fa)) {             // Check, if 4th array value (code) is in array
      $ns = $ns   $info[5];                   // plus to $ns, if yes
    } else {
      $s = $s   $info[5];                     // plus to $s, if no
    }
    unset($info);                             // clear array for next usage
  }
}

But it seems not cutting line into array. It just shows me lines, not dividing to array. I am using Summernote text editor, it sends data as rows.

CodePudding user response:

Because you're using $info[] = ... you get a 2 levels deep array instead of 1 level as your code is expecting. $info[] = ... basically means "Add the right hand side to $info as one element". So if the right hand side is a string and $info was empty before you'd get [0 => "my string"]. If the right hand side was an array you'd get [0 => [0 => "my", 1 => "array"]].

Do you see what I am getting at? Your code is adding one element to $info, never more than that. So to access anything in $info the first part needs to be $info[0]. But the code looks for the 4th and 5th elements, and they'll never be there. On the other hand, if you'd look for the 4th element inside the 1st one.. That is, $info[0] for the 1st element, and then the 4th inside it: $info[0][4], then you get what you're looking for.

if(!empty($_POST['indata'])){
  $in_data = $_POST['indata'];                // Get POST data
  $fa = array("OCS", "CSE");                  // Make array
  $ns = 0;                                    // Init ns value
  $s = 0;                                  // Init ss value
  foreach(explode("\n",$in_data) as $line){   // Divide text to lines
    $info[] = explode("    ", $line);         // Divide line to values and put them to array 
    if(in_array($info[0][4], $fa)) {             // Check, if 4th array value (code) is in array
      $ns = $ns   (int) $info[0][5];                   // plus to $ns, if yes
    } else {
      $s = $s   (int) $info[0][5];                     // plus to $s, if no
    }

    unset($info);
  }
}

var_dump($ns, $s); // int(29) int(18)

Version 2. Do away with one level in $info as mentioned earlier:

foreach(explode("\n",$in_data) as $line){
  $info = explode("    ", $line);
  if(in_array($info[4], $fa)) {
    $ns = $ns   (int) $info[5];
  } else {
    $s = $s   (int) $info[5];
  }
}

Alternative version, regexp:

foreach(explode("\n",$in_data) as $line){
  $info = preg_split('/\s{4,}/', $line); // Split when 4 or more spaces
  if(in_array($info[3], $fa)) {
      $ns = $ns   (int) $info[4];
  } else {
      $s = $s   (int) $info[4];
  }
}

That way you don't get any "junk columns" :).

Edit: I think it was PHP 7.1 that introduced some more "strictness" regarding adding values of different types, strings numbers that is. A notice is issued, "A non well formed numeric value encountered". But if the string is cast/converted as a number before summing PHP will accept it. Casting can be done by adding (int) in front of the string value. (Provided it contains an integer value, of course, otherwise it needs to be cast differently)

  • Related