user2093601
user2093601

Reputation: 402

Is there a shorter way to make this function?

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.

def front_x(words):
  xList = []
  nonXList = []
  for word in words:
    if word[0] == 'x':
      xList.append(word)
    else:
      nonXList.append(word)
  return sorted(xList) + sorted(nonXList)

I'm new to python and programming in general but I feel there is a more compact way to write this code or is there a more 'pythonic' way?

also I tried to return the line:

return xlist.sort() + nonXList.sort()

but this erred out. Why did that happen?

Upvotes: 2

Views: 568

Answers (7)

Andy_A̷n̷d̷y̷
Andy_A̷n̷d̷y̷

Reputation: 795

This works,and it's simple and easy to understand.

def front_x(words):
    xlist = [item for item in words if item[0] =='x']
    nonXList = [item for item in words if item[0] !='x']
    xlist.sort() # The .sort() method sorts a list alphabetically 
    nonXList.sort()
    Combined_Lists = xlist + nonXList
    return Combined_Lists
    #You can also comment Combined_Lists and 
    #just have return xlist + nonXList

Since you're new to Python,I tried to make it as simple as possible.

Upvotes: 2

unutbu
unutbu

Reputation: 879611

You could sort words with one call to sorted using the key parameter to "teach" sorted how you wish the items in words to be ordered:

def front_x(words):
    return sorted(words, key=lambda word: (word[0] != 'x', word))

The key function is called once for every item in words and returns a proxy value by which the items in words is to be sorted. tuples such as the one returned by the lambda function above, are sorted in lexicographic order (according to the first item in the tuple, and according to the second to break ties).

This technique as well as others is explained in the excellent Sorting Howto.


For example,

print(front_x(['mix', 'xyz', 'apple', 'xanadu', 'aardvark']))
# ['xanadu', 'xyz', 'aardvark', 'apple', 'mix']

Note that if words contains an empty string, word[0] will raise an IndexError. In contrast ''.startswith('x') returns False. So use word.startswith('x') if you wish front_x to handle empty strings, and use word[0] == 'x' if you wish to raise an exception.

Upvotes: 6

John La Rooy
John La Rooy

Reputation: 304205

The error is because .sort() is in-place. It returns None, and you can't do None + None

Since Python's sort is stable, you can also accomplish this by doing two sorts

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

And the in-place version

>>> L.sort()
>>> L.sort(key=lambda x:x[0]!='x')
>>> L
['xanadu', 'xyz', 'aardvark', 'apple', 'mix']

Upvotes: 0

Farhadix
Farhadix

Reputation: 1457

return sorted([w for w in words if w[0] == 'x']) + sorted([w for w in words if w[0] != 'x'])

Upvotes: 0

piokuc
piokuc

Reputation: 26184

>>> l = ['mix', 'xyz', 'apple', 'xanadu', 'aardvark'] 
>>> sorted ([x for x in l if x.startswith('x')]) + sorted([x for x in l if not x.startswith('x')])
['xanadu', 'xyz', 'aardvark', 'apple', 'mix']

Upvotes: 1

tom
tom

Reputation: 2365

Use list comprehensions

list =  ['mix', 'xyz', 'apple', 'xanadu', 'aardvark']
list.sort()
listA = [item for item in list if item[0] == 'x']
listB = [item for item in list if item[0] != 'x']
listC = listA + listB

Upvotes: 2

Dylan Lawrence
Dylan Lawrence

Reputation: 1533

The error for your return is because sort does not return a value, it merely modifies the list.

This seems a fairly fast way to do this, it runs in linear time, you won't get much faster than that. That being said, you could do inline code to shorten it, but it's not always more readable that way.

Upvotes: 1

Related Questions