SitePoint Sponsor

User Tag List

Results 1 to 18 of 18

Hybrid View

  1. #1
    SitePoint Zealot
    Join Date
    Mar 2003
    Location
    scarborough
    Posts
    140
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Delete element from within an array

    I have tried looking and cannot find it.

    If I have an array like this

    tt=array(10,2,23,14)

    How do I eliminate the number 23 from the array.

  2. #2
    SitePoint Zealot
    Join Date
    Mar 2003
    Location
    scarborough
    Posts
    140
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    What I mean specifically is to delete the element within the array ... totally... not leave it blank or null.

  3. #3
    SitePoint Wizard bronze trophy C. Ankerstjerne's Avatar
    Join Date
    Jan 2004
    Location
    The Kingdom of Denmark
    Posts
    2,702
    Mentioned
    7 Post(s)
    Tagged
    0 Thread(s)
    If you know that the value is the third one in the array:
    Code php:
    $tt = array(10, 2, 23, 14);
     
    unset($tt[2]);

    If you want to remove every element with the value 23:
    Code php:
    $tt = array(10, 2, 23, 14);
     
    foreach($tt as $key=>$value) {
     if($value == 23) {
      unset($tt[$key]);
     }
    }
    Christian Ankerstjerne
    <p<strong<abbr/HTML/ 4 teh win</>
    <>In Soviet Russia, website codes you!

  4. #4
    I solve practical problems. bronze trophy
    Michael Morris's Avatar
    Join Date
    Jan 2008
    Location
    Knoxville TN
    Posts
    2,053
    Mentioned
    66 Post(s)
    Tagged
    0 Thread(s)
    Today's entry of the PHP thread of the day series is relevant to this question.


    Quote Originally Posted by C. Ankerstjerne View Post
    If you know that the value is the third one in the array:
    Code php:
    $tt = array(10, 2, 23, 14);
     
    unset($tt[2]);

    If you want to remove every element with the value 23:
    Code php:
    $tt = array(10, 2, 23, 14);
     
    foreach($tt as $key=>$value) {
     if($value == 23) {
      unset($tt[$key]);
     }
    }
    No!

    First, this won't work - $value isn't bound to the source value array (To do this use "foreach ($array as $key => &$value)" and note the ampersand which causes the value to be passed by reference). Second, if you did receive the $value by reference, deleting a value on an object or array under iteration can cause undefined behavior by PHP.

  5. #5
    Non-Member bronze trophy
    Join Date
    Nov 2009
    Location
    Keene, NH
    Posts
    3,760
    Mentioned
    23 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Michael Morris View Post
    First, this won't work - $value isn't bound to the source value array (To do this use "foreach ($array as $key => &$value)" and note the ampersand which causes the value to be passed by reference).
    LOOK CLOSER. He's calling $tt (the parent) by key for the unset, NOT $value. As such you don't have to pull $value by reference! Not sure where you were going with that, but... no, you're WAY off the money there.

    Quote Originally Posted by Michael Morris View Post
    Second, if you did receive the $value by reference, deleting a value on an object or array under iteration can cause undefined behavior by PHP.
    unset inside foreach works just fine. First, foreach does the same thing as an array_walk, which is a pointer based operation using internal pointers... so the pointer to 'next' should still be valid even with the unset....

    Which is why his code runs just FINE!

    Oh, and array_filter and it's kine are problematic since you can't pass values to the user function and frankly heavy on the overhead (with the nested userland function call) is the slowest of them too... after mentioning it above I gave it a whirl, NOT worth the effort.

  6. #6
    I solve practical problems. bronze trophy
    Michael Morris's Avatar
    Join Date
    Jan 2008
    Location
    Knoxville TN
    Posts
    2,053
    Mentioned
    66 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by deathshadow60 View Post
    unset inside foreach works just fine. First, foreach does the same thing as an array_walk, which is a pointer based operation using internal pointers... so the pointer to 'next' should still be valid even with the unset....
    Should and is aren't always the same with PHP and you should know that by now.

    From the docs of array_walk
    Quote Originally Posted by array_walk documentation
    Only the values of the array may potentially be changed; its structure cannot be altered, i.e., the programmer cannot add, unset or reorder elements. If the callback does not respect this requirement, the behavior of this function is undefined, and unpredictable.
    I've seen PHP do bizarre things if you unset an element - particularly the element that will be next - in a foreach. Now granted, this behavior may have be fixed, but I long ago made it a point to avoid calling unset on the object I'm iterating on (I still do it when I absolutely need to, but that code gets extra heavy testing as a result).

  7. #7
    SitePoint Zealot
    Join Date
    Mar 2003
    Location
    scarborough
    Posts
    140
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It was slice I was looking for. It was just confusing because there are about thirty array functions.

  8. #8
    SitePoint Wizard bronze trophy C. Ankerstjerne's Avatar
    Join Date
    Jan 2004
    Location
    The Kingdom of Denmark
    Posts
    2,702
    Mentioned
    7 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Michael Morris View Post
    From the docs of array_walk
    foreach is different, though:
    Quote Originally Posted by PHP documentation
    Unless the array is referenced, foreach operates on a copy of the specified array and not the array itself. foreach has some side effects on the array pointer. Don't rely on the array pointer during or after the foreach without resetting it.
    Since the foreach is looping through a copy of the array, changing the original array will not alter the array which is being looped through, and thus, no conflict should occur.

    In other words, this:
    Code php:
    $array = array(1, 2, 1, 4, 1, 6, 1, 8, 1, 10);
     
    $needle = 1;
     
    foreach($array as $key=>$value) {
     if($value == $needle) {
      unset($array[$key]);
     }
    }

    should be functionally identical to this:
    Code php:
    $array = array(1, 2, 1, 4, 1, 6, 1, 8, 1, 10);
     
    $needle = 1;
     
    for($i = 0, $array_copy = $array, $length = count($array_copy); $i < $length; $i++) {
     if($array_copy[$i] == $needle) {
      unset($array[$i]);
     }
    }

    but not this:
    Code php:
    $array = array(1, 2, 1, 4, 1, 6, 1, 8, 1, 10);
     
    $needle = 1;
     
    for($i = 0, $length = count($array); $i < $length; $i++) {
     if($array[$i] == $needle) {
      unset($array[$i]);
     }
    }
    Christian Ankerstjerne
    <p<strong<abbr/HTML/ 4 teh win</>
    <>In Soviet Russia, website codes you!

  9. #9
    Non-Member bronze trophy
    Join Date
    Nov 2009
    Location
    Keene, NH
    Posts
    3,760
    Mentioned
    23 Post(s)
    Tagged
    0 Thread(s)
    That loop might be a bit inefficient/slow -- the unset can also cause set fragmentation slowing later iterations. This actually sucks a bit more RAM while running, but releases itself quickly enough:

    Code:
    $tt = array(10, 2, 23, 14);
    $tt=array_diff($tt,array('23'));
    Since array_diff returns all elements in the first array that don't match elements in the second array.

    Another approach would be to use array_search to find the matching key instead of iterating it.

    Code:
    if ($key=array_search('23',$tt)) unset($tt[$key]);
    Assuming there's only one. to check for multiple instances, I'd just use "while" instead of "if".

    An approach using array_filter may also be worth looking at.

  10. #10
    Keeper of the SFL StarLion's Avatar
    Join Date
    Feb 2006
    Location
    Atlanta, GA, USA
    Posts
    3,748
    Mentioned
    73 Post(s)
    Tagged
    0 Thread(s)
    Or just... not putting the 23 in the array in the first place... what input are you getting, and why do you need to remove one?
    Never grow up. The instant you do, you lose all ability to imagine great things, for fear of reality crashing in.

  11. #11
    SitePoint Wizard silver trophybronze trophy Cups's Avatar
    Join Date
    Oct 2006
    Location
    France, deep rural.
    Posts
    6,869
    Mentioned
    17 Post(s)
    Tagged
    1 Thread(s)
    Do the keys have to retain their original values or not?

  12. #12
    SitePoint Wizard silver trophybronze trophy Cups's Avatar
    Join Date
    Oct 2006
    Location
    France, deep rural.
    Posts
    6,869
    Mentioned
    17 Post(s)
    Tagged
    1 Thread(s)
    No, there's about 80 (or there was about 3 years ago when I counted them all).

  13. #13
    I solve practical problems. bronze trophy
    Michael Morris's Avatar
    Join Date
    Jan 2008
    Location
    Knoxville TN
    Posts
    2,053
    Mentioned
    66 Post(s)
    Tagged
    0 Thread(s)
    And don't you just love that most array functions have arguments in the order (needle, haystack) and most string functions work in (haystack, needle) order?? heh heh - Love PHP, but I don't love it's inconsistencies.

  14. #14
    @php.net Salathe's Avatar
    Join Date
    Dec 2004
    Location
    Edinburgh
    Posts
    1,397
    Mentioned
    65 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Michael Morris View Post
    most array functions have arguments in the order (needle, haystack) and most string functions work in (haystack, needle) order??
    At least they're consistent within those two, completely unrelated, groups of functions. I never understood how folks get hung up on this particular setup; maybe we shouldn't have used the term "needle" and "haystack" for both groups.
    Salathe
    Software Developer and PHP Manual Author.

  15. #15
    I solve practical problems. bronze trophy
    Michael Morris's Avatar
    Join Date
    Jan 2008
    Location
    Knoxville TN
    Posts
    2,053
    Mentioned
    66 Post(s)
    Tagged
    0 Thread(s)
    No, it isn't consistent. str_replace and str_ireplace is (needle, replace, haystack)

    I still feel the defining feature of PHP 6 should be shunting all existing functions to a legacy namespace. With a php.ini setting enabled the legacy namespace is imported to the root namespace. Otherwise the whole function library should be redone in an object oriented manner. All arrays would be array objects with the array methods tied to them, same with strings. This would be an enormous change and unlikely to ever occur, but it would be the perfect time to address these problems while using the ini flag to maintain BC.

  16. #16
    @php.net Salathe's Avatar
    Join Date
    Dec 2004
    Location
    Edinburgh
    Posts
    1,397
    Mentioned
    65 Post(s)
    Tagged
    0 Thread(s)
    Fine, mostly consistent. Way to pick on the minor things.
    Salathe
    Software Developer and PHP Manual Author.

  17. #17
    Non-Member bronze trophy
    Join Date
    Nov 2009
    Location
    Keene, NH
    Posts
    3,760
    Mentioned
    23 Post(s)
    Tagged
    0 Thread(s)
    That does rank amongst my pet peeves about PHP -- namespace and parameter orders. It literally feels like they just rolled a D6 on the order of parameters in functions... maybe it's the machine language/assembly coder in me, but come on... pick one, AT&T (dest, value) or Intel (target, value)... don't mix and match willy-nilly.

    But it's like function, class and method names... camelcase, don't camelcase, underscores, don't underscore... PICK ONE!

  18. #18
    @php.net Salathe's Avatar
    Join Date
    Dec 2004
    Location
    Edinburgh
    Posts
    1,397
    Mentioned
    65 Post(s)
    Tagged
    0 Thread(s)
    This is only partly an excuse, but PHP does have coding standards for naming. The other side of the coin is that much of PHP is based on the names of the C functions being called behind-the-scenes.
    Salathe
    Software Developer and PHP Manual Author.


Bookmarks

Posting Permissions

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