Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 7 of 7
  1. #1
    Regular Coder
    Join Date
    Sep 2011
    Posts
    213
    Thanks
    15
    Thanked 5 Times in 5 Posts

    Exclamation in_array bugging my code

    I have this code here that i use for a chat bot. The problem is, the in_array part doesn't seem to be working correctly. I marked the lines with errors with a comment explaining the details of it.

    PHP Code:
    <?php
    //Details of the function:
    /*
    $contests stores the array of contests
    $contests is stored as $contests[hostID] = details
    $message is the message received
    $contest[0] is the host
    $contest[1] is the details

    EX: $contest[test] = "This is a test contest";
    "test" is the host and "This is a test contest" is the details
    */
    function contestCommand($packet,$message,$type){
        global 
    $bot$commandCode$contest_MinRank;
        
    $contests $bot->getDB('contests');
        
    $message explode(' ',@$message[1],2);
        switch(
    $message[0]){
            case 
    'add':
                if(!
    $bot->minRank($packet['u'],$contest_MinRank)) return;
                
    $contest explode(' ',$message[1],2);
                if(!
    $contest[0] || !$contest[1]) { $bot->respond("Usage: ".$commandCode."contest add [host] [details]",$type,$packet['u']); return;}
                if(
    in_array($contest[0],$contests)) { $bot->respond("Only one contest per user!",$type,$packet['u']); return;}//The problem is the check to see if the contest is added or not.
                
    $contests[$contest[0]] = $contest[1];
                
    $bot->updateDB('contests',$contests);
                
    $bot->respond("Contest added! (".$packet['u'].")",$type,$packet['u']);
            break;
            case 
    'remove':
                if(!
    $bot->minRank($packet['u'],$contest_MinRank)) return;
                
    $contest explode(' ',$message[1],2);
                if(!
    $contest$bot->respond("Usage: ".$commandCode."contest remove [host]",$type,$packet['u']);
                if(!
    in_array($contest[0],$contests)) { $bot->respond("No contest for this user!",$type,$packet['u']); return;}
                
    $contests array_diff($contests,array($contest[0]));//Doesn't remove properly. Plan on fixing later unless aswered here
                
    $bot->updateDB('contests',$contests);
                
    $bot->respond("Contest removed! (".$packet['u'].")",$type,$packet['u']);
            break;
            default:
                foreach(
    $contests as $host => $details){
                    
    $ua $bot->getUserArray($host);
                    if(
    $ua['registered']) $host==$ua['registered'];
                    
    $bot->sendPC($packet['u'],"[$host] - $details");
                }
        }
    }
    ?>
    Last edited by Dubz; 11-22-2011 at 10:22 PM.

  • #2
    God Emperor Fou-Lu's Avatar
    Join Date
    Sep 2002
    Location
    Saskatoon, Saskatchewan
    Posts
    16,979
    Thanks
    4
    Thanked 2,659 Times in 2,628 Posts
    What is $message? The description leads me to believe that this is a string, but its being used as an array. Since you overwrite the $message within the function itself, its later uses would be an array potentially.

    Either the in_array is wrong, or the assignment below is wrong. The assignment below indicates that $contest[0] is a key within the array with the value of $contest[1]. The in_array works for values, not for keys. If you want to detect a key existing, use either isset($array['key']) or use array_key_exists('key', $array). The former is faster, while the latter will return true for null values.
    Similar issue to the array_diff, assuming its been associated. Use unset($array['key']) instead.

  • #3
    Regular Coder
    Join Date
    Sep 2011
    Posts
    213
    Thanks
    15
    Thanked 5 Times in 5 Posts
    Quote Originally Posted by Fou-Lu View Post
    What is $message? The description leads me to believe that this is a string, but its being used as an array. Since you overwrite the $message within the function itself, its later uses would be an array potentially.

    Either the in_array is wrong, or the assignment below is wrong. The assignment below indicates that $contest[0] is a key within the array with the value of $contest[1]. The in_array works for values, not for keys. If you want to detect a key existing, use either isset($array['key']) or use array_key_exists('key', $array). The former is faster, while the latter will return true for null values.
    Similar issue to the array_diff, assuming its been associated. Use unset($array['key']) instead.
    This script is for a chat bot.
    before the function, $message is set to the message sent. then it is exploded into $message as $message[0] (the first word) and $message[1] (everything after). the first word indicates the command (which is the function) and runs it. while it is in the function, it takes the $message[1] of the initial message and explodes it again. now we have $message[0] as the second word of the message and $message[1] as everything else. the second word is used as a switch (to add or remove a contest or list for the default). if it hits a case, the $message[1] is exploded again into $contest which is set so the third word of the message is the host and everything else is the details of the contest.

    Simplified, its like this:
    First word: $message[0] -> (command)
    Second word: $message[1]/$message[0](after explode) -> (switch)
    Third word: $contest[0] -> (host)
    Fourth+ word(s): $contest[1] -> (details)

    The 'if(in_array' line for the add case is supposed to check if $contest[0] is already set in $contests and if so, do the action stated

    The same for the remove case except it checks to see if it exists. If it doesn't, it tells the user that it never had one. If it does, it removes it.

    Also with the unset part, an advanced php coding friend of mine who originally coded this bot told me to use array_diff and not unset because unset just clears the value of the memory while array_diff unallocates it after clearing it, freeing up space

  • #4
    Senior Coder
    Join Date
    Feb 2011
    Location
    Your Monitor
    Posts
    4,091
    Thanks
    51
    Thanked 506 Times in 493 Posts
    Quote Originally Posted by Dubz View Post
    Also with the unset part, an advanced php coding friend of mine who originally coded this bot told me to use array_diff and not unset because unset just clears the value of the memory while array_diff unallocates it after clearing it, freeing up space
    No, array_diff returns the difference between two arrays. It isn't intended for deleting parts of an array at all. Your advanced php friend should of pointed you to the php manual for an explanation.
    My helpful sig is on vacation trying to loose some weight. It got a bit fat and caused a few problems but it will be back at some point!

  • #5
    God Emperor Fou-Lu's Avatar
    Join Date
    Sep 2002
    Location
    Saskatoon, Saskatchewan
    Posts
    16,979
    Thanks
    4
    Thanked 2,659 Times in 2,628 Posts
    Quote Originally Posted by Dubz View Post
    Also with the unset part, an advanced php coding friend of mine who originally coded this bot told me to use array_diff and not unset because unset just clears the value of the memory while array_diff unallocates it after clearing it, freeing up space
    This can't be right. There is no way in PHP to force the freeing of memory at all (aside from C sourced extensions in which case we better be freeing it, but that said we emalloc anyway so PHP will kindly clean up after us ). We can request it do so using unset or over-writing an assignment, but both of these will execute via efree from the garbage collection. Array_diff itself does nothing to free memory, and will actually consume additional pointers to the hashtable* buckets to generate a new list. PHP's copy-on-write optimizing will limit the size of the returned bucket to sizeof(zval*) * bucket size, but will certainly provide at minimum sizeof(zval). I would expect that both the assignment over top of a variable and unset effectively produce the same end result for memory freeing, but using a function like array_diff is guaranteed to consume more memory overall.

    Still doesn't change what I have said. These lines conflict:
    PHP Code:
                if(in_array($contest[0],$contests)) { $bot->respond("Only one contest per user!",$type,$packet['u']); return;}//The problem is the check to see if the contest is added or not.
                
    $contests[$contest[0]] = $contest[1]; 
    Lets say $contest[0] = 'test' and $contest[1] = 'this is a test'. $contests is an array of 'test' => 'this is a test'. Using in_array will seek the value of a result, so providing the above will return false since the only value available is 'this is a test'. The next line dictates that $contests is to be provided with a value of 'this is a test' with an associative index of 'test'. This is where the conflict is - you need to use either array_key_exists or isset instead of the in_array.
    The same follows for array_diff. Either unset it instead, or use array_diff giving it the value (ie: $contest[1]) as the array to work with. Array_diff only cares about the values, not the keys (although you can force key checking as well using array_diff_assoc, but that will dictate both the key and the value must match).

  • Users who have thanked Fou-Lu for this post:

    Dubz (11-25-2011)

  • #6
    Regular Coder
    Join Date
    Sep 2011
    Posts
    213
    Thanks
    15
    Thanked 5 Times in 5 Posts
    Quote Originally Posted by Fou-Lu View Post
    This can't be right. There is no way in PHP to force the freeing of memory at all (aside from C sourced extensions in which case we better be freeing it, but that said we emalloc anyway so PHP will kindly clean up after us ). We can request it do so using unset or over-writing an assignment, but both of these will execute via efree from the garbage collection. Array_diff itself does nothing to free memory, and will actually consume additional pointers to the hashtable* buckets to generate a new list. PHP's copy-on-write optimizing will limit the size of the returned bucket to sizeof(zval*) * bucket size, but will certainly provide at minimum sizeof(zval). I would expect that both the assignment over top of a variable and unset effectively produce the same end result for memory freeing, but using a function like array_diff is guaranteed to consume more memory overall.

    Still doesn't change what I have said. These lines conflict:
    PHP Code:
                if(in_array($contest[0],$contests)) { $bot->respond("Only one contest per user!",$type,$packet['u']); return;}//The problem is the check to see if the contest is added or not.
                
    $contests[$contest[0]] = $contest[1]; 
    Lets say $contest[0] = 'test' and $contest[1] = 'this is a test'. $contests is an array of 'test' => 'this is a test'. Using in_array will seek the value of a result, so providing the above will return false since the only value available is 'this is a test'. The next line dictates that $contests is to be provided with a value of 'this is a test' with an associative index of 'test'. This is where the conflict is - you need to use either array_key_exists or isset instead of the in_array.
    The same follows for array_diff. Either unset it instead, or use array_diff giving it the value (ie: $contest[1]) as the array to work with. Array_diff only cares about the values, not the keys (although you can force key checking as well using array_diff_assoc, but that will dictate both the key and the value must match).
    I used the array_key_exists instead of in_array and it works great now. i used unset too after i figured out because array_diff was just clearing the array. Thanks!
    Last edited by Dubz; 11-25-2011 at 01:18 AM.

  • #7
    Senior Coder
    Join Date
    Feb 2011
    Location
    Your Monitor
    Posts
    4,091
    Thanks
    51
    Thanked 506 Times in 493 Posts
    Quote Originally Posted by Dubz View Post
    i figured out because array_diff was just clearing the array.
    No it wasn't even doing that. You still don't understand what it does. It compares TWO arrays and returns the DIFFERENCE between them as another array.

    It doesn't clear or delete anything.
    My helpful sig is on vacation trying to loose some weight. It got a bit fat and caused a few problems but it will be back at some point!


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •