-2

I'm trying to order my array. My first array will have values string values few of them will be same now i want to know how many of each value is there and add that to a new array as key and value the number of how many times it appears in first array now i get to do this yet i get a bug.

Last entry instead of being counter in gets added extra.

I tried while/for/foereach same result.

Code:

<?php
 function add_fit($fitting)
   {
        // Save raw fit
        $eft = $fitting;

        // Clean for import
        $fit = trim($fitting);
        $lines = explode("\n", $fit);
        $lines = array_filter($lines, 'trim');

        // Split first line for name and type
        $details = str_replace('[', '', $lines[0]);
        $details = str_replace(']', '', $details);
        $split_details = explode(', ', $details);

        $ship = $split_details[0];
        $name = $split_details[1];

        foreach ($lines as $line => $module) {
            if(strstr($module, '[empty '))
            {
                unset($lines[$line]);
            }
        }

        $all = array();
        foreach ($lines as $index => $segment) {
            array_push($all, $segment);
        }

        $modules = array();
        for($i = 1; $i < count($all); $i++)
        {
            if(isset($modules[$all[$i]]))
            {
                $modules[$all[$i]] = $modules[$all[$i]]+1;
            } else {
                $modules[$all[$i]] = 1;
            }
        }

        var_dump($modules);

   }

/*
The $fitting is as follows:

[Thrasher, Buffer Thrasher]
Gyrostabilizer II
Gyrostabilizer II

Small F-S9 Regolith Shield Induction
Small F-S9 Regolith Shield Induction
1MN MicroWarpdrive I

280mm Howitzer Artillery II
280mm Howitzer Artillery II
280mm Howitzer Artillery II
280mm Howitzer Artillery II
280mm Howitzer Artillery II
280mm Howitzer Artillery II
280mm Howitzer Artillery II
[empty high slot]

Small Ancillary Current Router I
Small Ancillary Current Router I
Small Ancillary Current Router I


And the method returns:
  'Gyrostabilizer II'                    => int 2
  'Small F-S9 Regolith Shield Induction' => int 2
  '1MN MicroWarpdrive I'                 => int 1
  '280mm Howitzer Artillery II'          => int 7
  'Small Ancillary Current Router I'     => int 2
  'Small Ancillary Current Router I'     => int 1


While it should return:
  'Gyrostabilizer II'                    => int 2
  'Small F-S9 Regolith Shield Induction' => int 2
  '1MN MicroWarpdrive I'                 => int 1
  '280mm Howitzer Artillery II'          => int 7
  'Small Ancillary Current Router I'     => int 3   <-- Like this
*/

?>
Sterling Duchess
  • 1,970
  • 16
  • 51
  • 91

2 Answers2

0

You must have some non-printing characters in your input, as a hash can't have the same key with multiple values (which is what your output shows - two keys of Small Ancillary Current Router I, which must be different as they have different values . . . )

What's a var_dump(array_keys($modules)) show?

Solution is to better sanitize your input - looks like you should probably add something in your cleanup section . . . maybe something like this to strip UTF, or if that's the last line in your input, there may be an EOF character in there . . .

Edit: From your comments, the var_dump output is:

5 => string 'Small Ancillary Current Router I' (length=33) 
6 => string 'Small Ancillary Current Router I' (length=32)

Note that one is 33 and the other is 32, meaning a non-printing character is causing differences. A shotgun approach to removing all non-printing characters is described here. To implement in your code:

    $all = array();
    foreach ($lines as $segment) {
        $all[] = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $segment);
    }
Community
  • 1
  • 1
ernie
  • 6,356
  • 23
  • 28
  • Tried but still the same problem. – Sterling Duchess Sep 27 '12 at 22:57
  • 5 => string 'Small Ancillary Current Router I' (length=33) 6 => string 'Small Ancillary Current Router I' (length=32) They are diffirent lengths im asuming there are non printable chars in former but i cant remove them any way i try str replace, trim, perg_match etc. – Sterling Duchess Sep 27 '12 at 23:31
  • What's your `trim` function that you're using as the callback in array_filter look like? – ernie Sep 27 '12 at 23:33
  • It just calls trim again to remove any extra \r characters left behind. – Sterling Duchess Sep 27 '12 at 23:36
  • I still get the same thing. Only way i dont get two keys named the same like that is if in my input i add another line of text at the end. Then i get both Small Ancil.. under one key and value saying 3 as it should but then i also have another meaningless entry – Sterling Duchess Sep 27 '12 at 23:40
  • I have found the solution i cgabged my explode to explode('\r\n', $lists); Now it displays as it should. – Sterling Duchess Sep 27 '12 at 23:46
-1

You should probably be using array_key_exists() rather than isset. The reason can be seen in this SO question

Either way you have some whitespace causing the problem. Try adding a trim to the following line and it should work:

foreach ($lines as $index => $segment) { 
    array_push($all, $segment); 
} 

Change to:

foreach ($lines as $index => $segment) { 
    array_push($all, trim($segment)); 
} 

And BTW: o7 fly safe ;-)

UPDATE: heres the code I used for testing:

<!DOCTYPE html>
<html>

<head>
</head>
<body>
<?php 

$whatever = "[Thrasher, Buffer Thrasher] 
Gyrostabilizer II 
Gyrostabilizer II 

Small F-S9 Regolith Shield Induction 
Small F-S9 Regolith Shield Induction 
1MN MicroWarpdrive I 

280mm Howitzer Artillery II 
280mm Howitzer Artillery II 
280mm Howitzer Artillery II 
280mm Howitzer Artillery II 
280mm Howitzer Artillery II 
280mm Howitzer Artillery II 
280mm Howitzer Artillery II 
[empty high slot] 

Small Ancillary Current Router I 
Small Ancillary Current Router I 
Small Ancillary Current Router I";

echo '<pre>';
print_r(add_fit($whatever));
echo '</pre>';


 function add_fit($fitting) 
   { 
        // Save raw fit 
        $eft = $fitting; 

        // Clean for import 
        $fit = trim($fitting); 
        $lines = explode("\n", $fit); 
        $lines = array_filter($lines, 'trim'); 

        // Split first line for name and type 
        $details = str_replace('[', '', $lines[0]); 
        $details = str_replace(']', '', $details); 
        $split_details = explode(', ', $details); 

        $ship = $split_details[0]; 
        $name = $split_details[1]; 

        foreach ($lines as $line => $module) { 
            if(strstr($module, '[empty ')) 
            { 
                unset($lines[$line]); 
            } 
        } 

        $all = array(); 
        foreach ($lines as $index => $segment) { 
            array_push($all, trim($segment)); 
        } 

        $modules = array(); 
        for($i = 1; $i < count($all); $i++) 
        { 
            if(isset($modules[$all[$i]])) 
            { 
                $modules[$all[$i]] = $modules[$all[$i]]+1; 
            } else { 
                $modules[$all[$i]] = 1; 
            } 
        } 

        return $modules; 

   } 

?>
</body>
</html>
Community
  • 1
  • 1
Zappa
  • 453
  • 1
  • 5
  • 14
  • Hey mate i tried array_key_exists() and triming the $segment but thats not it the first two modules in last key are 33 in length while the last module is 32 in length yet they show everything the same. Weird tho i trimed away all \r and \n. Also fly safe o7 – Sterling Duchess Sep 27 '12 at 22:55
  • @kellax: I tried your code in my test bed and adding the trim fixed the output the way you wanted. Not sure what could be different in your setup apart from an encoding issue/difference. You using apache, IIS, etc? And what version of PHP? – Zappa Sep 27 '12 at 22:58
  • Im using WAMP with PHP 5.4.3, page encoding is set to utf8 i also tried preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $segment) When i do a var_dump on the $modules array i get the last key's length 32 and one before it 33 so there is a non printable char somewhere not getting removed. – Sterling Duchess Sep 27 '12 at 23:04
  • Also I assumed that the input $fitting value was a string. – Zappa Sep 27 '12 at 23:04
  • $fitting is direct $_POST from a – Sterling Duchess Sep 27 '12 at 23:06
  • Weird thing tho if i add another entry in to $all array ad the end then Small Ac.. is displayed correctly however then i have a key in the array i dont need. – Sterling Duchess Sep 27 '12 at 23:16
  • I have updated my answer with the exact code I used for testing in case it helps you. – Zappa Sep 27 '12 at 23:36
  • @ernie: yes fair enough and agreed. I was only pasting my code for reference by kellax for a comparison. – Zappa Sep 27 '12 at 23:43
  • I have found the solution i cgabged my explode to explode('\r\n', $lists); Now it displays as it should. – Sterling Duchess Sep 27 '12 at 23:46
  • Seriously. A downvote? Thanks to whoever gave that. So much for trying to be helpful. – Zappa Sep 27 '12 at 23:51