简体   繁体   English

递归对嵌套列表中的所有元素进行平方

[英]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.我只知道如何使用列表索引来解决这个问题,但是这里不允许这个解决方案,因为问题已经说明我必须在函数中包含“for x in nums”。 I know that int is immutable, so what can I do?我知道 int 是不可变的,那我该怎么办? Thanks for the hint of "isinstance", but I'm sorry that we have not learned it before so I cannot use it in exams.感谢“isinstance”的提示,但很抱歉我们之前没有学过,所以我不能在考试中使用它。

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.编写一个 python 函数square_all ,它接受一个参数,一个整数嵌套列表,并返回一个新的整数嵌套列表,该列表在结构上与给定列表相同,但其中所有整数都已平方。 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.但是,此函数仅支持list作为嵌套对象。 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 .如果您希望您的函数支持所有可迭代对象,您应该对collections.Iterable进行isinstance检查。 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] .您的代码的问题在于您创建了一个列表,因此仅调用square_all(new[i])不会更改new[i] You have to assign the result: new[i] = square_all(new[i]) .您必须分配结果: 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]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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