0
\$\begingroup\$

I'm solving exercise 3 from lecture 3 of Berkeley's CS 61A (2012):

Fill in the definition of map_tuple. map_tuple takes in a function and a tuple as arguments and applies the function to each element of the tuple.

def map_tuple(func, tup):
    """Applies func to each element of tup and returns a new tuple.
    >>> a = (1, 2, 3, 4)
    >>> func = lambda x: x * x
    >>> map_tuple(func, a)
    (1, 4, 9, 16)
    """

I know that Python has a built-in map function, but at this point in the course, the only operations on tuples that we have studied are indexing [1] [-1], slicing [1:], and concatenation +, so my solution needs to restrict itself accordingly.

My solution 1:

def map_tuple(func, tup):
    """Applies func to each element of tup and returns a new tuple.

    >>> a = (1, 2, 3, 4)
    >>> func = lambda x: x * x
    >>> map_tuple(func, a)
    (1, 4, 9, 16)
    """
    length = len(tup)
    count = 0
    new_tuple = ()
    while count < length:
        new_tuple = new_tuple +  (func(tup[count]),)
        count = count + 1
    return new_tuple

My solution 2:

def map_tuple_recursive(func, tup):
    """Applies func to each element of tup and returns a new tuple.

    >>> a = (1, 2, 3, 4)
    >>> func = lambda x: x * x
    >>> map_tuple(func, a)
    (1, 4, 9, 16)
    """
    length = len(tup)
    def new_tuple(count):
        if count == length:
            return ()
        else:
            return (func(tup[count]), ) + new_tuple(count + 1)
    return new_tuple(0)

How can these solutions be improved?

\$\endgroup\$
4
  • \$\begingroup\$ What's wrong with tuple(map(func, tup))? \$\endgroup\$ Apr 13, 2015 at 15:47
  • \$\begingroup\$ purpose of the exercise is to understand + , , and slicing amidst usage of tuples \$\endgroup\$ Apr 13, 2015 at 15:51
  • \$\begingroup\$ Can you edit the question to explain the constraints, and where they come from? Is this for a programming class? I mean, throw us a bone here. \$\endgroup\$ Apr 13, 2015 at 15:53
  • \$\begingroup\$ It looks like you haven't solved the challenge. Solution 1 uses mutation (count = count + 1). Neither solution uses really uses the operations you mentioned (except the obligatory tup[count]). \$\endgroup\$ Apr 13, 2015 at 16:51

1 Answer 1

5
\$\begingroup\$

Assuming you cannot us generator expressions (which technically are not mutable but I can see being outside the scope of the assignment), solution 1 can be simplified by iterating over the items of the tuple, and by use the += in-place append:

def map_tuple(func, tup):
    """
    Applies func to each element of tup and returns a new tuple.

    >>> a = (1, 2, 3, 4)
    >>> func = lambda x: x * x
    >>> map_tuple(func, a)
    (1, 4, 9, 16)
    """
    new_tuple = ()
    for itup in tup:
        new_tuple += (func(itup),)
    return new_tuple

The second can be simplified by looking for the case where the tuple is empty, and if it is not empty return the map of everything except the last element, plus the function applied to the last element:

def map_tuple_recursive(func, tup):
    """Applies func to each element of tup and returns a new tuple.

    >>> a = (1, 2, 3, 4)
    >>> func = lambda x: x * x
    >>> map_tuple(func, a)
    (1, 4, 9, 16)
    """
    if not tup:
       return ()
    return map_tuple_recursive(func, tup[:-1]) + (func(tup[-1],)

Using a generator expression lets you do this, but maybe outside the scope of what you are allowed to do:

def map_tuple_gen(func, tup):
    """
    Applies func to each element of tup and returns a new tuple.

    >>> a = (1, 2, 3, 4)
    >>> func = lambda x: x * x
    >>> map_tuple(func, a)
    (1, 4, 9, 16)
    """
    return tuple(func(itup) for itup in tup)
\$\endgroup\$
5
  • \$\begingroup\$ generator expression? \$\endgroup\$ Apr 13, 2015 at 16:02
  • \$\begingroup\$ A generator expression is something like (func(x) for x in iterable). It is list a list comprehension, [func(x) for x in iterable], except instead of doing everything at once and loading it into memory as list, it does it in a lazy manner, working on one item at a time and loading the result into memory only when needed. \$\endgroup\$ Apr 13, 2015 at 16:05
  • \$\begingroup\$ why not tup is true when tup is ()? Because type(()) gives <class 'tuple'> \$\endgroup\$ Apr 14, 2015 at 4:04
  • \$\begingroup\$ What is in-place append? Because >>> a = (1, ) >>> id(a) 63144232 >>> b = 2 >>> a += (b, ) >>> id(a) 59954696 >>> \$\endgroup\$ Apr 14, 2015 at 4:16
  • \$\begingroup\$ Empty lists, strings and tuples in python are considered False. For in-place appends, a += b is the same as a = a+b. For tuples, it isn't "in-place" in the meaning of "in the same object", since tuples are immutable, but it is "in-place" in the meaning of "operating on the same variable". It sounds like you are still very new to python, I think it would be worthwhile working through some beginner tutorials on python. \$\endgroup\$ Apr 14, 2015 at 7:29

Your Answer

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

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