1
\$\begingroup\$

I wrote a function that adds items in a list, but my professor says to try and write it in a simpler way because he says I take too many steps. Is there any other way to write this?

def additems(self, item):
    """Add <item> to this PriorityQueue.

    @type self: PriorityQueue
    @type item: object
    @rtype: None

    >>> pq = PriorityQueue()
    >>> pq.additems("yellow")
    >>> pq.additems("blue")
    >>> pq.additems("red")
    >>> pq.additems("green")
    >>> pq._items
    ['blue', 'green', 'red', 'yellow']
    """
    # TODO
    #only insert if the list isn't already empty
    if not self.is_empty():

        i = 0

        #Look for the lowest priority place to insert the item
        while i < len(self._items):


            if item <= self._items[i]:
                self._items.insert(i, item)

                #exit the loop if it inserts
                i = len(self._items)

            elif item >= self._items[-1]:
                self._items.append(item)

                #exit the loop if it inserts
                i = len(self._items)

            i += 1

    else:
        self._items.append(item)
\$\endgroup\$
  • \$\begingroup\$ Can you please describe what this code is supposed to do? \$\endgroup\$ – David Foerster Feb 20 '16 at 9:08
  • \$\begingroup\$ Your title says "adding items to a list", but I have a feeling the exercise is really about "adding items to a priority queue", which is veeeeery different. And when your prof says you're taking "too many steps", does he mean too many statements written in the code, or too many steps executed? I suspect the latter, and that this exercise is about reducing computational complexity (make algorithm faster), not about shortening the code. Please clarify. \$\endgroup\$ – janos Feb 21 '16 at 7:34
2
\$\begingroup\$

You don't present the entire code for the class here, but the usage of self and the doctests within the docstring indicates that you are actually using a class. As such my first order would be that in the initialisation of the class you always create the _items list, which would remove the need to check whether there are elements or not when adding elements.

To use i = len(self._items) to terminate the loop is a hackish solution. It would be better to use break instead. But while and for (and actually try ... except) allows for the usage of else which can help out in this particular case. In short, if the loop terminates ordinarily, the else part is executed, if you break out of it, it'll not be executed.

In stead of doing the while i < len(self._items) loop, which requires calculating the length multiple times, and doesn't look to Pythonic, I would suggest using for i, item in enumerate(self._items). This loop construct loops over all the elements (if any) and gives the index of the current element (due to the use of enumerate()).

Lastly, naming the method additems() when you only add one element is misleading and not following standards. A better name would be add_item().

This leads to the following code:

class PriorityQueue(object):

    def __init__(self):
        self._items = []


    def add_item(self, new_item):
        """Add items into queue at correct place."""

        for i, item in enumerate(self._items):
            if new_item < item:
                self._items.insert(i, new_item)
                break
        else:
            self._items.append(new_item)


def main():
    pq = PriorityQueue()
    pq.add_item("yellow")
    pq.add_item("blue")
    pq.add_item("red")
    pq.add_item("green")

    print(pq._items)

if __name__ == '__main__':
    main()

I'm sorry that the environment I tested this in doesn't support doctests, but this does output the correct list of ['blue', 'green', 'red', 'yellow'].

|improve this answer|||||
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.