简体   繁体   中英

recursion to square all elements in nested lists

I failed to answer this question in my midterm. I am NOT asking you guys to do homework for me. Just want to know how to solve this problem. I only know how to solve this problem using list index, but this solution is not allowed here because the question has stated that I have to include "for x in nums" in the function. I know that int is immutable, so what can I do? Thanks for the hint of "isinstance", but I'm sorry that we have not learned it before so I cannot use it in exams.

I had just learned how to solve similar problems using index. I think it can work like this:

def square_all(nums):
    new = []
    for x in nums:
        new.append(x)
    for i in range(len(new)):
        if type(new[i]) != list:
            new[i] = new[i] ** 2
        else:
            square_all(new[i])
    return new

It doesn't work well. I think there is something wrong with 'else'. But how should I modify?

Write a python function square_all that takes one parameter, a nested list of integers, and returns a new nested list of integers that is structurally identical to the given list, but in which all of the integers have been squared. Note that the function should no modify its parameter; it should build a new, separate list.

Complete the function by writing anything you think is needed above, within or below the loop. Don't write code outside of the function. Assume that there are no global variables available to you. don't make changes to the code that has been provided.

Example:

 square_all([1,2,[3,4]]) = [1,4,[9,16]]

Given code:

 def square_all(nums;'nested list of integers') -> 'nested list of integers': for x in nums:

This a very general solution to this problem:

def map_nested(fnc, obj):
    if isinstance(l, (list, set, tuple)):  # whatever collection type you want
        return type(obj)(map_nested(fnc, sub) for sub in obj)
    return fnc(obj)        

> map_nested(lambda x: x**2, [1, 2, (3, 4, set([5, 6]))])
[1, 4, (9, 16, set([25, 36]))]

You may create your recursive function as:

def get_square(l):
    return [get_square(e) if isinstance(e, list) else e**2 for e in l]
    #                           ^ to check object is of `list` type

Sample run:

>>> get_square([1,2,[3,4]])
[1, 4, [9, 16]]

However, this function will only support list as the nested object. It will fail in case you pass tuple as nested structure. For example:

>>> get_square([1,2,(3,4)])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in get_square
TypeError: unsupported operand type(s) for ** or pow(): 'tuple' and 'int'

In case you want your function to support all the iterables, you should be doing isinstance check for collections.Iterable . Hence your function should be like:

from collections import Iterable

def get_square(l):
    return type(l)(get_square(e) if isinstance(e, Iterable) else e**2 for e in l)
    #        ^                        ^ check for `collections.Iterable`
    #        ^ for preserving the type of `Iterables`

Sample run:

>>> get_square([1,2,(3,4)])
[1, 4, (9, 16)]

The problem with your code is that you create a new list, thus just calling square_all(new[i]) won't change new[i] . You have to assign the result: new[i] = square_all(new[i]) .

def square_all(nums):
    new = []
    for x in nums:
        new.append(x)
    for i in range(len(new)):
        if type(new[i]) != list:
            new[i] = new[i] ** 2
        else:
            new[i] = square_all(new[i])  # assign result to new[i]
    return new

Or a bit shorter, directly appending the final values instead of first using the original values and then overwriting them later:

def square_all(nums):
    result = []
    for n in nums:
        if type(n) is list:
            result.append(square_all(n))
        else:
            result.append(n**2)
    return result

Or really short, using the given code in a list comprehension:

def square_all(nums):
    return [square_all(n) if type(n) is list else n**2 for n in nums]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM