remove an item from string list

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • python101
    New Member
    • Sep 2007
    • 90

    remove an item from string list

    I have a string list

    items = ['B','D','B','A' ,'E']

    Assume that I don't know the order (index) of these items. I would like to remove the second 'B' out of the list without sorting [using items.sort() ] or changing the the order of other items in the list. How can I do that?

    The remove() and pop(), only take the first 'B' or I have to know the index of the second 'B' to remove second 'B' out.
  • bartonc
    Recognized Expert Expert
    • Sep 2006
    • 6478

    #2
    Originally posted by python101
    I have a string list

    items = ['B','D','B','A' ,'E']

    Assume that I don't know the order (index) of these items. I would like to remove the second 'B' out of the list without sorting [using items.sort() ] or changing the the order of other items in the list. How can I do that?

    The remove() and pop(), only take the first 'B' or I have to know the index of the second 'B' to remove second 'B' out.
    [CODE=python]
    >>> items = ['B','D','B','A' ,'E']
    >>> list(set(items) )
    ['A', 'B', 'E', 'D']
    >>> [/CODE]Hmmm... That shouldn't have reordered the list. I'll keep at it..

    Comment

    • bartonc
      Recognized Expert Expert
      • Sep 2006
      • 6478

      #3
      Originally posted by bartonc
      [CODE=python]
      >>> items = ['B','D','B','A' ,'E']
      >>> list(set(items) )
      ['A', 'B', 'E', 'D']
      >>> [/CODE]Hmmm... That shouldn't have reordered the list. I'll keep at it..
      [CODE=python]
      >>> for i, item in enumerate(items[:]): #loop through a copy of the list
      ... try:
      ... j = items.index(ite m, i + 1)
      ... items.pop(j)
      ... except ValueError:
      ... pass
      ...
      >>> items
      ['B', 'D', 'A', 'E']
      >>> [/CODE]

      Comment

      • python101
        New Member
        • Sep 2007
        • 90

        #4
        Originally posted by bartonc
        [CODE=python]
        >>> items = ['B','D','B','A' ,'E']
        >>> list(set(items) )
        ['A', 'B', 'E', 'D']
        >>> [/CODE]Hmmm... That shouldn't have reordered the list. I'll keep at it..
        I mentioned that I did not know the order of the list in items, I only knew that there was two 'B' in the list. In your case, we would have to know the order of all items.

        Comment

        • python101
          New Member
          • Sep 2007
          • 90

          #5
          Originally posted by bartonc
          [CODE=python]
          >>> for i, item in enumerate(items[:]): #loop through a copy of the list
          ... try:
          ... j = items.index(ite m, i + 1)
          ... items.pop(j)
          ... except ValueError:
          ... pass
          ...
          >>> items
          ['B', 'D', 'A', 'E']
          >>> [/CODE]
          Thank you very much. However, is there a simpler way to pop second 'B' out without using loop?

          Comment

          • bartonc
            Recognized Expert Expert
            • Sep 2006
            • 6478

            #6
            Originally posted by python101
            Thank you very much. However, is there a simpler way to pop second 'B' out without using loop?
            Two tricks here:
            1) Start searching for the index one past the location of the first occurrence.
            2) Wrap the index() method in a try block in case it fails.[CODE=python]
            >>> items = ['B','D','B','A' ,'E']
            >>> try:
            ... j = items.index('B' , 1) # one past the location of the first occurrence
            ... items.pop(j)
            ... except ValueError:
            ... pass
            ...
            >>> items
            ['B', 'D', 'A', 'E']
            >>> [/CODE]

            Comment

            • python101
              New Member
              • Sep 2007
              • 90

              #7
              Originally posted by bartonc
              Two tricks here:
              1) Start searching for the index one past the location of the first occurrence.
              2) Wrap the index() method in a try block in case it fails.[CODE=python]
              >>> items = ['B','D','B','A' ,'E']
              >>> try:
              ... j = items.index('B' , 1) # one past the location of the first occurrence
              ... items.pop(j)
              ... except ValueError:
              ... pass
              ...
              >>> items
              ['B', 'D', 'A', 'E']
              >>> [/CODE]
              Thank you. I got the trick

              Comment

              • python101
                New Member
                • Sep 2007
                • 90

                #8
                I just thought another way to approach the problem. Could I determine all indexs of 'B' in the list, so when there were numberous 'B's in the list I would be able to pop B at any certain index?

                Comment

                • bvdet
                  Recognized Expert Specialist
                  • Oct 2006
                  • 2851

                  #9
                  Originally posted by python101
                  I just thought another way to approach the problem. Could I determine all indexs of 'B' in the list, so when there were numberous 'B's in the list I would be able to pop B at any certain index?
                  I have used this function many times:[code=Python]"""
                  Return an index list of all occurrances of 'item' in string/list 's'.
                  Optional start search position 'i'
                  """
                  def indexList(s, item, i=0):
                  i_list = []
                  while True:
                  try:
                  i = s.index(item, i)
                  i_list.append(i )
                  i += 1
                  except:
                  break
                  return i_list[/code]

                  >>> items = ['B','D','B','A' ,'E']
                  >>> indexList(items , 'B')
                  [0, 2]
                  >>>

                  Comment

                  • ilikepython
                    Recognized Expert Contributor
                    • Feb 2007
                    • 844

                    #10
                    Originally posted by bvdet
                    I have used this function many times:[code=Python]"""
                    Return an index list of all occurrances of 'item' in string/list 's'.
                    Optional start search position 'i'
                    """
                    def indexList(s, item, i=0):
                    i_list = []
                    while True:
                    try:
                    i = s.index(item, i)
                    i_list.append(i )
                    i += 1
                    except:
                    break
                    return i_list[/code]

                    >>> items = ['B','D','B','A' ,'E']
                    >>> indexList(items , 'B')
                    [0, 2]
                    >>>
                    I don't know about you, but I think this is clearer:
                    [code=python]
                    def indexList(s, item, start = 0):
                    i_list = []
                    for (i, obj) in enumerate(s[start:]):
                    if obj == item:
                    i_list.append(i + start)
                    return i_list
                    [/code]
                    or with map:
                    [code=python]
                    def indexList(s, item, start = 0):
                    return filter(lambda x: x, map(lambda (i, obj): i + start if obj == item else None, enumerate(s[start:]))) # i think i over did it
                    [/code]I think yours is faster for larger lists though.

                    EDIT:
                    List comprhension is definately clearer:
                    [code=python]
                    def indexList(s, item, start = 0):
                    return [i + start for (i, obj) in enumerate(s[start:]) if obj == item]
                    [/code]

                    Comment

                    • bvdet
                      Recognized Expert Specialist
                      • Oct 2006
                      • 2851

                      #11
                      Originally posted by ilikepython
                      I don't know about you, but I think this is clearer:
                      [code=python]
                      def indexList(s, item, start = 0):
                      i_list = []
                      for (i, obj) in enumerate(s[start:]):
                      if obj == item:
                      i_list.append(i + start)
                      return i_list
                      [/code]
                      or with map:
                      [code=python]
                      def indexList(s, item, start = 0):
                      return filter(lambda x: x, map(lambda (i, obj): i + start if obj == item else None, enumerate(s[start:]))) # i think i over did it
                      [/code]I think yours is faster for larger lists though.

                      EDIT:
                      List comprhension is definately clearer:
                      [code=python]
                      def indexList(s, item, start = 0):
                      return [i + start for (i, obj) in enumerate(s[start:]) if obj == item]
                      [/code]
                      Thanks ilikepython. I like your code. I have not done any tests for efficiency. It's good to see alternate methods that accomplish the same goal.

                      Comment

                      • ghostdog74
                        Recognized Expert Contributor
                        • Apr 2006
                        • 511

                        #12
                        Originally posted by python101
                        I have a string list

                        items = ['B','D','B','A' ,'E']

                        Assume that I don't know the order (index) of these items. I would like to remove the second 'B' out of the list without sorting [using items.sort() ] or changing the the order of other items in the list. How can I do that?

                        The remove() and pop(), only take the first 'B' or I have to know the index of the second 'B' to remove second 'B' out.
                        go with the basics. The basics are very important
                        Code:
                        >>> items = ['B','D','B','A','E']
                        >>> start=items.index('B') #get the first "B" position
                        >>> print start
                        0
                        >>> second = items[start+1:].index("B") # get the second "B"
                        >>> print second 
                        1
                        >>> index_to_remove = second + 1 #add 1 to get exact position of second "B" since we started search 1 position after the first "B"
                        >>> items.pop(index_to_remove)
                        'B'
                        >>> items
                        ['B', 'D', 'A', 'E']
                        >>>

                        Comment

                        • ilikepython
                          Recognized Expert Contributor
                          • Feb 2007
                          • 844

                          #13
                          Originally posted by bvdet
                          Thanks ilikepython. I like your code. I have not done any tests for efficiency. It's good to see alternate methods that accomplish the same goal.
                          The only problem is it doesn't work for patterns. Like, to search for "ACC" in "ACACCAAACC ".

                          Comment

                          Working...