2

I'm doing an exercise as following:

# B. front_x
# Given a list of strings, return a list with the strings
# in sorted order, except group all the strings that begin with 'x' first.
# e.g. ['mix', 'xyz', 'apple', 'xanadu', 'aardvark'] yields
# ['xanadu', 'xyz', 'aardvark', 'apple', 'mix']
# Hint: this can be done by making 2 lists and sorting each of them
# before combining them.

sample solution:

def front_x(words):
  listX = []
  listO = []

  for w in words:
    if w.startswith('x'):
      listX.append(w)
    else:
      listO.append(w)

  listX.sort()
  listO.sort()

  return listX + listO

my solution:

def front_x(words):
  listX = []

  for w in words:
    if w.startswith('x'):
      listX.append(w)
      words.remove(w)

  listX.sort()
  words.sort()

  return listX + words  

as I tested my solution, the result is a little weird. Here is the source code with my solution: http://dl.dropbox.com/u/559353/list1.py. You might want to try it out.

2
  • 2
    Do you have any specific question, except "What's wrong with my code"? Commented Dec 22, 2010 at 11:02
  • -1: "the result is a little weird". Vague and difficult to answer. Please provide something specific that you'd like to fix. Commented Dec 22, 2010 at 14:26

4 Answers 4

3

The problem is that you loop over the list and remove elements from it (modifying it):

for w in words:
    if w.startswith('x'):
      listX.append(w)
      words.remove(w)

Example:

>>> a = range(5)
>>> for i in a:
...  a.remove(i)
... 
>>> a
[1, 3]

This code works as follows:

  • Get first element, remove it.
  • Move to the next element. But it is not 1 anymore because we removed 0 previously and thus 1 become the new first element. The next element is therefore 2 and 1 is skipped.
  • Same for 3 and 4.
Sign up to request clarification or add additional context in comments.

1 Comment

yeah, i see. in your example, after removing 0 from a, 1 becomes the 0th element and will be skipped in the next loop.
1

Two main differences:

  1. Removing an element from a list inside loop where the list is being iterated doesn't quite work in Python. If you were using Java you would get an exception saying that you are modifying a collection that is being iterated. Python doesn't shout this error apparently. @Felix_Kling explains it quite well in his answer.
  2. Also you are modifying the input parameter words. So the caller of your function front_x will see words modified after the execution of the function. This behaviour, unless is explicitly expected, is better to be avoided. Imagine that your program is doing something else with words. Keeping two lists as in the sample solution is a better approach.

Comments

0

Altering the list you're iterating over results in undefined behaviour. That's why the sample solution creates two new lists instead of deleting from the source list.

for w in words:
  if w.startswith('x'):
    listX.append(w)
    words.remove(w) # Problem here!

See this question for a discussion on this matter. It basically boils down to list iterators iterating through the indexes of the list without going back and checking for modifications (which would be expensive!).

If you want to avoid creating a second list, you will have to perform two iterations. One to iterate over words to create listX and another to iterate over listX deleting from words.

Comments

0

That hint is misleading and unnecessary, you can do this without sorting and combining two lists independently:

>>> items = ['mix', 'xyz', 'apple', 'xanadu', 'aardvark']
>>> sorted(items, key=lambda item: (item[0]!='x', item))
['xanadu', 'xyz', 'aardvark', 'apple', 'mix']

The built-in sorted() function takes an option key argument that tells it what to sort by. In this case, you want to create a tuples like (False, 'xanadu') or (True, 'apple') for each element of the original list, which you can do with a lambda.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.