I'm new in Python but basically I want to create sub-groups of element from the list with a double loop, therefore I gonna compare the first element with the next to figure out if I can create these sublist, otherwise I will break the loop inside and I want continue with the last element but in the main loop:
Example: 5,7,8,4,11
Compare 5 with 7, is minor? yes so include in the newlist and with the inside for continue with the next 8, is minor than 5? yes, so include in newlist, but when compare with 4, I break the loop so I want continue in m with these 4 to start with the next, in this case with 11...
for m in xrange(len(path)):
for i in xrange(m+1,len(path)):
if (path[i] > path[m]):
newlist.append(path[i])
else:
break
m=m+i
Thanks for suggestions or other ideas to achieve it!
P.S.
Some input will be:
input: [45,78,120,47,58,50,32,34]
output: [45,78,120],[47,58],50,[32,34]
The idea why i want make a double loops due to to compare sub groups of the full list,in other way is while 45 is minor than the next one just add in the new list, if not take the next to compare in this case will be 47 and start to compare with 58.
No loop!
Well at least, no explicit looping...
import itertools
def process(lst):
# Guard clause against empty lists
if len(lst) < 1:
return lst
# use a dictionary here to work around closure limitations
state = { 'prev': lst[0], 'n': 0 }
def grouper(x):
if x < state['prev']:
state['n'] += 1
state['prev'] = x
return state['n']
return [ list(g) for k, g in itertools.groupby(lst, grouper) ]
Usage (work both with Python 2 & Python 3):
>>> data = [45,78,120,47,58,50,32,34]
>>> print (list(process(data)))
[[45, 78, 120], [47, 58], [50], [32, 34]]
Joke apart, if you need to group items in a list itertools.groupby deserves a little bit of attention. Not always the easiest/best answer -- but worth to make a try...
EDIT: If you don't like closures -- and prefer using an object to hold the state, here is an alternative:
class process:
def __call__(self, lst):
if len(lst) < 1:
return lst
self.prev = lst[0]
self.n = 0
return [ list(g) for k, g in itertools.groupby(lst, self._grouper) ]
def _grouper(self, x):
if x < self.prev:
self.n += 1
self.prev = x
return self.n
data = [45,78,120,47,58,50,32,34]
print (list(process()(data)))
EDIT2: Since I prefer closures ... but #torek don't like the dictionary syntax, here a third variation around the same solution:
import itertools
def process(lst):
# Guard clause against empty lists
if len(lst) < 1:
return lst
# use an object here to work around closure limitations
state = type('State', (object,), dict(prev=lst[0], n=0))
def grouper(x):
if x < state.prev:
state.n += 1
state.prev = x
return state.n
return [ list(g) for k, g in itertools.groupby(lst, grouper) ]
data = [45,78,120,47,58,50,32,34]
print (list(process(data)))
I used a double loop as well, but put the inner loop in a function:
#!/usr/bin/env python
def process(lst):
def prefix(lst):
pre = []
while lst and (not pre or pre[-1] <= lst[0]):
pre.append(lst[0])
lst = lst[1:]
return pre, lst
res=[]
while lst:
subres, lst = prefix(lst)
res.append(subres)
return res
print process([45,78,120,47,58,50,32,34])
=> [[45, 78, 120], [47, 58], [50], [32, 34]]
The prefix function basically splits a list into 2; the first part is composed of the first ascending numbers, the second is the rest that still needs to be processed (or the empty list, if we are done).
The main function then simply assembles the first parts in a result lists, and hands the rest back to the inner function.
I'm not sure about the single value 50; in your example it's not in a sublist, but in mine it is. If it is a requirement, then change
res.append(subres)
to
res.append(subres[0] if len(subres)==1 else subres)
print process([45,78,120,47,58,50,32,34])
=> [[45, 78, 120], [47, 58], 50, [32, 34]]
#uselpa's version is fine. Here's mine (same issue with [50] instead of just 50) that uses collections.deque to be a little more efficient, and also some long comments...
#! /usr/bin/env python
from collections import deque
def process(lst):
"""
Given a list of values that is not sorted (such that for some
valid indices i,j, i<j, sometimes lst[i] > lst[j]), produce a
new list-of-lists, such that in the new list, each sublist *is*
sorted:
for all sublist \elem returnval:
assert_is_sorted(sublist)
and furthermore this is the minimal set of sublists required
to achieve the condition.
Thus, if the input list lst is actually sorted, this returns
[list(lst)].
"""
def sublist(deq):
"""
Pop items off the front of deque deq until the next one
goes backwards. Return the constructed sub-list.
"""
sub = [deq.popleft()]
while deq and deq[0] >= sub[-1]:
sub.append(deq.popleft())
return sub
# Make a copy of lst before modifying it; use a deque so that
# we can pull entries off it cheaply.
deq = deque(lst)
output = []
ret = []
while deq:
ret.append(sublist(deq))
return ret
print process([45,78,120,47,58,50,32,34])
(Incidentally, in the days before collections.deque I'd probably just use a reversed copy of lst and use lst.pop() in sublist. That's not quite as obvious, though.)
why not simply use a single for loop instead of using itertool and all fancy stuff.
def list_test(inlist, outlist):
if not inlist:
return []
prev=inlist[0]
x=[]
for item in inlist:
if item >= prev:
x.append(item)
else:
outlist.append(x)
x=[]
x.append(item)
prev=item
if x:
outlist.append(x)
in_list=[1,0,1,2,3]
out_list = []
list_test(in_list, out_list)
print(out_list)
O/p:[[1], [0, 1, 2, 3]]
Related
I am new to python and struggling with nested lists. In particular, I have been given a nested list from which I need to extract the deepest list (or lists, if there are more than one list at the deepest depth). I've coded the below, but it's only returning one of the two deepest lists (the other one would be [4421, 4422]). Could someone explain what I'm doing wrong? There's a related question from before but, similarly, the suggested solutions could only provide the first of two deepest lists. Thank you.
def deepest_list(l):
deeps = []
for item in l:
if isinstance(item, list):
return deepest_list(item)
else:
deeps.append(item)
continue
return deeps
deepest_list([1, [21, [[2211, 2212], 222]], [[311], 32, [331]], [41, 42, 43, [441, [4421, 4422]]]])
There are two issues you need to deal with:
When you do return deepest_list(item) it breaks the execution of the function, including the loop, so any remaining items are not considered.
The straight-forward recursive logic, on which the code is based, is not suitable for the problem. It is not enough to find the deepest list(s) in any given sublist, you also need to know its depth, in order to compare it with the deepest list(s) in another sublist. In other words, correct code would have to remember the depth as well as the identity of the deepest list(s).
Try this:
def deepest_lists(lst):
lsts = [item for item in lst if isinstance(item, list)]
if len(lsts) == 0:
return lsts
if all(isinstance(item, int) for lst in lsts for item in lst):
return lsts
return deepest_lists([item for lst in lsts for item in lst])
Example:
>>> lst = [1, [21, [[2211, 2212], 222]], [[311], 32, [331]], [41, 42, 43, [441, [4421, 4422]]]]
>>> deepest_lists(lst)
[[2211, 2212], [4421, 4422]]
I would divide the problem in three parts:
You can find the sequence of indices needed to get to each innermost list in the list (e.g., if you have l = [[1,2], [[23, [12]]], the indices to get to 1 would be (0,0), as you would access it as l[0][0], and the indices to get to 2 would be (1,)).
From these indices, you can select the ones with the highest length, as they represent the deepest list.
From the original list, you select the elements that are represented in the list of the deepest indices.
Something like the following:
# Get from original list, using a list of tuples representing the indices of the wanted elements
def LookupByTuple(data, tuples):
ret = []
for t in tuples:
answer = data
for i in t:
answer = answer[i]
ret.append(answer)
return ret
def deepest_ids(data, id=(), indices = set()):
# Find the indices to get to each innermost list
for i,elem in enumerate(data):
if isinstance(elem, list):
deepest_ids(elem, id + (i,), indices)
else:
indices.add(id)
ids = list(indices)
indices = None
# Select the deepest indices
maxlen = max(map(len, ids))
ret = [s for s in ids if len(s) == maxlen]
return ret
Which then gives you
>> l = [1, [21, [[2211, 2212], 222]], [[311], 32, [331]], [41, 42, 43, [441, [4421, 4422]]]]
>> LookupByTuple(l, deepest_ids(l))
>> [[4421, 4422], [2211, 2212]]
This solution works also when the input list only has one level:
>> l = [1,2,3]
>> LookupByTuple(l, deepest_ids(l))
>> [[1,2,3]]
My actual example is more involved so I boiled the concept down to a simple example:
l = [1,2,3,4,5,6,7,8]
for number in l:
calc = number*10
print calc
For each iteration of my loop, I end up with a variable (calc) I'd like to use to populate a new list. My actual process involves much more than multiplying the value by 10, so I'd like to be able to set each value in the new list by this method. The new code might look like this:
l = [1,2,3,4,5,6,7,8]
for number in l:
calc = number*10
# set calc as x'th entry in a new list called l2 (x = iteration cycle)
print l2
Then it would print the new list: [10,20,30,40,...]
There are several options...
List comprehensions
Use list comprehension, if short enough:
new_list = [number * 10 for number in old_list]
map()
You could also use map(), if the function exists before (or you will eg. use lambda):
def my_func(value):
return value * 10
new_list = map(my_func, old_list)
Be aware, that in Python 3.x map() does not return a list (so you would need to do something like this: new_list = list(map(my_func, old_list))).
Filling other list using simple for ... in loop
Alternatively you could use simple loop - it is still valid and Pythonic:
new_list = []
for item in old_list:
new_list.append(item * 10)
Generators
Sometimes, if you have a lot of processing (as you said you have), you want to perform it lazily, when requested, or just the result may be too big, you may wish to use generators. Generators remember the way to generate next element and forget whatever happened before (I am simplifying), so you can iterate through them once (but you can also explicitly create eg. list that stores all the results).
In your case, if this is only for printing, you could use this:
def process_list(old_list):
for item in old_list:
new_item = ... # lots of processing - item into new_item
yield new_item
And then print it:
for new_item in process_list(old_list):
print(new_item)
More on generators you can find in Python's wiki: http://wiki.python.org/moin/Generators
Accessing "iteration number"
But if your question is more about how to retrieve the number of iteration, take a look at enumerate():
for index, item in enumerate(old_list):
print('Item at index %r is %r' % (index, item))
Here's how to do it without jumping straight into list comprehensions. It's not a great idea to use l as a variable name because it is identical to 1 in some fonts, so I changed it (althought l1 isn't really much better :) )
l1 = [1,2,3,4,5,6,7,8]
l2 = []
for number in l1:
calc = number*10
print calc
l2.append(calc)
list comprehensions do provide a more compact way to write this pattern
l2 = [ number*10 for number in l1 ]
Use a list comprehension :
>>> l = [1,2,3,4,5,6,7,8]
>>> l2 = [ item*10 for item in l]
>>> l2
[10, 20, 30, 40, 50, 60, 70, 80]
Which is roughly equivalent to, but a list comprehension is faster than normal for-loop:
>>> l2 = []
>>> for number in l:
... calc = number * 10 #do some more calculations
... l2.append(calc) #appends the final calculated value at the end of l2
...
>>> l2
[10, 20, 30, 40, 50, 60, 70, 80]
You can also create a function for all the calculations you're doing, and then call the function inside the list comprehension :
def solve(x):
#do some calculations here
return calculated_value
l2 = [ solve(item) for item in l]
So I believe you would like to apply a function to every element of the list.
Have you tried a list comprehension?
[num*10 for num in l]
Should give you what you need for this simple example.
Naturally, if you have some more complex set of operations you can use a function you defined earlier, to wit:
def explode(n):
return (n + (n * n) - (3 * n))
[explode(num) for num in l]
A simple answer to your problem would be to append calc to a list as shown below:
l = [1,2,3,4,5,6,7,8]
your_list = []
for number in l:
calc = number*10
your_list.append(calc)
To access variables in the list, use slicing syntax.
ie, the 2nd element in a list would be your_list[1], the 5th your_list[4].
I suspect you'll need to empty the list at some point. To do so with slicing, use calc[:] = []
Everyone else has given you the right answer: use a list comprehension.
I will give you an alternate right answer: Use map with a lambda or a function.
You can use a lambda when the 'function' is very simple:
print map(lambda x: x*10,[1,2,3,4,5,6,7,8])
# [10, 20, 30, 40, 50, 60, 70, 80]
The function used by map can be of arbitrary complexity, and then it is easier use a function:
def more_complex(x):
# can be as complex as a function can be
# for now -- *10
return x*10
print map(more_complex,[1,2,3,4,5,6,7,8])
But that would work with a comprehension as well:
l2=[more_complex(x) for x in [1,2,3,4,5,6,7,8]]
Just so that you are familiar with the form of map vs list comprehension.
loop that generates the list
KOT = []
l = [1,2,3,4,5,6,7,8]
for number in l:
calc = number*10
KOT.append(calc)
You get the KOT list
KOT = [10, 20, 30, 40, 50, 60, 70, 80]
I want to rotate k element in a list in python. For example, n = 7, k = 3, and the array [1,2,3,4,5,6,7] is rotated to [5,6,7,1,2,3,4].
Here is the statement I wrote. It seems to work in the command line.
nums = nums[k%len(nums):] + nums[:k%len(nums)]
But when I encapsulate it in a function like:
def rotate(nums, k):
nums = nums[k%len(nums):] + nums[:k%len(nums)]
return
I want to modify nums directly, but this function doesn't work.
I know that I can use a for loop like:
for i in range(k):
nums.insert(0,nums.pop())
but I want to know why the previous method doesn't work?
What you want is a slice assignment:
nums[:] = nums[k%len(nums):] + nums[:k%len(nums)]
This mutates the list that was passed in, so the change is visible after the function returns. Assigning just to nums merely makes nums point to a different list inside the function; it doesn't affect the original list.
Are you sure you want to modify nums? You need not create a separate list even if you do not modify nums. One advantage of the following approach is that it will work with any sequence.
from itertools import islice
def rotate(lst, k):
n = len(lst)
start = n - (k % n) #handle all ints
for item in islice(lst, start, None):
yield item
for item in islice(lst, 0, start):
yield item
If you insist on modifying nums as you say, you can still do so. E.g.,
nums = [x + 1 for x in range(7)]
nums[:] = rotate(nums,-10)
The nums that is inside the function is only within that function. So you need to return it from that function. One way is like this (python 2.7 code, add parentheses to print if you use 3.x):
nums = [1, 2, 3, 4, 5, 6, 7]
k = 3
def rotate(nums, k):
return nums[k%len(nums):] + nums[:k%len(nums)]
print 'Original', nums
nums = rotate(nums, k)
print 'Rotated', nums
This question already has answers here:
sum of nested list in Python
(14 answers)
Closed 8 years ago.
for example I have a list with numbers like this:
a = [10,[20,30],40]
or
b = [[10,20],30]
Now I have to add all the elements in the above lists.
so that if add the first list then I should get the answer as follows: 10+20+30+40 = 100.
and for the second one b as follows: 10+20+30 = 60.
The solution is to be expressed as a function.
I have tried this one but it can be used for only adding if there is no nested list.
def sum(t):
total = 0
for x in t:
total = total+x
return total
Now can anyone help me solve this kind of problem in python programming.
Thank you in advance!!!!!
You can use reduce:
x = reduce(lambda prev,el: prev+([x for x in el] if type(el) is list else [el]), x, [])
And use its result to feed your loop.
def sum(t):
t = reduce(lambda prev,el: prev+([x for x in el] if type(el) is list else [el]), t, [])
total = 0
for x in t:
total = total+x
return total
You can recursively flatten into a single list:
def flatten(lst, out=None):
if out is None:
out = []
for item in lst:
if isinstance(item, list):
flatten(item, out)
else:
out.append(item)
return out
Now you can just use sum:
>>> sum(flatten([10, [20, 30], 40]))
100
You need to define a recursion to handle the nested lists:
rec = lambda x: sum(map(rec, x)) if isinstance(x, list) else x
rec, applied on a list, will return the sum (recursively), on a value, return the value.
result = rec(a)
Seems like the best approach would be to iterate over the top-level list and check each element's type (using is_instance(type, item)). If it's an integer, add it to the total, otherwise if it's a list, iterate over that list.
Making your function recursive would make it most usable.
Edit: For anybody stumbling upon this question, here's an example.
def nested_sum(input_list):
total = 0
for element in input_list:
if isinstance(element, int):
total += element
elif isinstance(element, list):
total += nested_sum(element)
else:
raise TypeError
return total
Usage:
my_list = [72, 5, [108, 99, [8, 5], 23], 44]
print nested_sum(my_list)
>>> 364
My actual example is more involved so I boiled the concept down to a simple example:
l = [1,2,3,4,5,6,7,8]
for number in l:
calc = number*10
print calc
For each iteration of my loop, I end up with a variable (calc) I'd like to use to populate a new list. My actual process involves much more than multiplying the value by 10, so I'd like to be able to set each value in the new list by this method. The new code might look like this:
l = [1,2,3,4,5,6,7,8]
for number in l:
calc = number*10
# set calc as x'th entry in a new list called l2 (x = iteration cycle)
print l2
Then it would print the new list: [10,20,30,40,...]
There are several options...
List comprehensions
Use list comprehension, if short enough:
new_list = [number * 10 for number in old_list]
map()
You could also use map(), if the function exists before (or you will eg. use lambda):
def my_func(value):
return value * 10
new_list = map(my_func, old_list)
Be aware, that in Python 3.x map() does not return a list (so you would need to do something like this: new_list = list(map(my_func, old_list))).
Filling other list using simple for ... in loop
Alternatively you could use simple loop - it is still valid and Pythonic:
new_list = []
for item in old_list:
new_list.append(item * 10)
Generators
Sometimes, if you have a lot of processing (as you said you have), you want to perform it lazily, when requested, or just the result may be too big, you may wish to use generators. Generators remember the way to generate next element and forget whatever happened before (I am simplifying), so you can iterate through them once (but you can also explicitly create eg. list that stores all the results).
In your case, if this is only for printing, you could use this:
def process_list(old_list):
for item in old_list:
new_item = ... # lots of processing - item into new_item
yield new_item
And then print it:
for new_item in process_list(old_list):
print(new_item)
More on generators you can find in Python's wiki: http://wiki.python.org/moin/Generators
Accessing "iteration number"
But if your question is more about how to retrieve the number of iteration, take a look at enumerate():
for index, item in enumerate(old_list):
print('Item at index %r is %r' % (index, item))
Here's how to do it without jumping straight into list comprehensions. It's not a great idea to use l as a variable name because it is identical to 1 in some fonts, so I changed it (althought l1 isn't really much better :) )
l1 = [1,2,3,4,5,6,7,8]
l2 = []
for number in l1:
calc = number*10
print calc
l2.append(calc)
list comprehensions do provide a more compact way to write this pattern
l2 = [ number*10 for number in l1 ]
Use a list comprehension :
>>> l = [1,2,3,4,5,6,7,8]
>>> l2 = [ item*10 for item in l]
>>> l2
[10, 20, 30, 40, 50, 60, 70, 80]
Which is roughly equivalent to, but a list comprehension is faster than normal for-loop:
>>> l2 = []
>>> for number in l:
... calc = number * 10 #do some more calculations
... l2.append(calc) #appends the final calculated value at the end of l2
...
>>> l2
[10, 20, 30, 40, 50, 60, 70, 80]
You can also create a function for all the calculations you're doing, and then call the function inside the list comprehension :
def solve(x):
#do some calculations here
return calculated_value
l2 = [ solve(item) for item in l]
So I believe you would like to apply a function to every element of the list.
Have you tried a list comprehension?
[num*10 for num in l]
Should give you what you need for this simple example.
Naturally, if you have some more complex set of operations you can use a function you defined earlier, to wit:
def explode(n):
return (n + (n * n) - (3 * n))
[explode(num) for num in l]
A simple answer to your problem would be to append calc to a list as shown below:
l = [1,2,3,4,5,6,7,8]
your_list = []
for number in l:
calc = number*10
your_list.append(calc)
To access variables in the list, use slicing syntax.
ie, the 2nd element in a list would be your_list[1], the 5th your_list[4].
I suspect you'll need to empty the list at some point. To do so with slicing, use calc[:] = []
Everyone else has given you the right answer: use a list comprehension.
I will give you an alternate right answer: Use map with a lambda or a function.
You can use a lambda when the 'function' is very simple:
print map(lambda x: x*10,[1,2,3,4,5,6,7,8])
# [10, 20, 30, 40, 50, 60, 70, 80]
The function used by map can be of arbitrary complexity, and then it is easier use a function:
def more_complex(x):
# can be as complex as a function can be
# for now -- *10
return x*10
print map(more_complex,[1,2,3,4,5,6,7,8])
But that would work with a comprehension as well:
l2=[more_complex(x) for x in [1,2,3,4,5,6,7,8]]
Just so that you are familiar with the form of map vs list comprehension.
loop that generates the list
KOT = []
l = [1,2,3,4,5,6,7,8]
for number in l:
calc = number*10
KOT.append(calc)
You get the KOT list
KOT = [10, 20, 30, 40, 50, 60, 70, 80]