可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Im trying to write a function that takes a list and can print the lowest integer that is within that list. Now i'm trying to figure out what to do where this works with nested lists that if the lowest number is within one of those nested lists then overall it will print that number. My code is here:
def listMin():
list2 = [3,4,[2,99,8],7]
for i in range (len(list2)):
if type(list2[i]) == type([]):
y=min(i)
list2.append(y)
print "hello"
if len(list2)== 0:
return None
else:
x= min(list2)
print x
listMin()
while this seems like it should print the number 2 it doesnt and just gives me an error once it reaches the nested list saying:
TypeError: 'int' object is not iterable
ive tried multiple things but i'm having a hard time as to why this sort of thing isn't working.
回答1:
In general, you could flatten your list of lists and search for min in the flattened list. There are many recipes for flattening. Here is one that I took from here.
import collections
def flatten(iterable):
for el in iterable:
if isinstance(el, collections.Iterable) and not isinstance(el, str):
yield from flatten(el)
else:
yield el
list2 = [3,4,[2,99,8],7]
print(list(flatten(list2)))
# [3, 4, 2, 99, 8, 7]
print(min(flatten(list2)))
# 2
This will work on multiple nested list as well, e.g.:
list2 = [3,4,[2,99,8,[-1,-2]],7]
print(list(flatten(list2)))
# [3, 4, 2, 99, 8, -1, -2, 7]
print(min(flatten(list2)))
# -2
回答2:
Nesting One Deep
In your example, the list is nested only one deep. If this is the case in general, then try:
>>> list2 = [3,4,[2,99,8],7]
>>> min(x if isinstance(x, int) else min(x) for x in list2)
2
Nesting of Arbitrary Depth
If deeper nesting is allowed, define this recursive function:
>>> def rmin(lst): return min(x if isinstance(x, int) else rmin(x) for x in lst)
...
In operation:
>>> rmin(list2)
2
Or, with deeper nesting:
>>> list3 = [3,4,[[2,99],8],7]
>>> rmin(list3)
2
>>> list4 = [3, 4, [[2, [99, 1]], 8], 7]
>>> rmin(list4)
1
How it works
The function rmin
consists of the single line:
return min(x if isinstance(x, int) else rmin(x) for x in lst)
As you can see, this is a list comprehension that looks at every value x
of the list lst
.
Let's divide the argument of min
into two parts. The first is:
x if isinstance(x, int) else rmin(x)
This returns x
if x
is an integer. Otherwise, it calls rmin
on x
. In the latter case, rmin
recursively looks at every value in x
and returns the minimum.
The second part of the argument of min
is:
for x in lst
This is just the usual for a list comprehension. It extracts each value in lst
in turn and assigns it to x
.
回答3:
The problem is caused by the line
y=min(i)
where i
is an integer but not a list. You probably want y = min(list2[i])
.
Note that while you have appended this y
back to the original list, the loop would not reach the newly added element, since i
will only range up to the original length of the list.
With some simple Python idioms, your original idea can be expressed in a more readable way as follows:
def listMin():
lst = [3,4,[2,99,8],7]
for x in lst:
if type(x) == list:
lst.append(min(x))
print min(lst)
listMin()
回答4:
When I needed to do something similar, I wrote following:
import copy
def nestedMin(list_):
target_list = copy.deepcopy(list_) # to keep original list unchanged
for index in range (len(target_list)):
if type (target_list[index]) is list:
target_list[index] = nestedMin(target_list[index])
return min(target_list)
I know that it is not very efficient, keeps doing deepcopy; but it's readable and it does the job :)
Example:
list1 = [2,3,[4, -5, [7, -20]]]
print nestedMin(list1) # prints -20
print list1 # prints [2, 3, [4, -5, [7, -20]]]