Modifying nested lists - python

How to handle nested lists in Python? I am having problem figuring out the syntax. Like example:
>>> l = [[1, 2, 3], [5, 6, 7]]
I want to square all the elements in this list. I tried:
[m*m for m in l]
But that doesn't work and throws up:
TypeError: can't multiply sequence by
non-int of type 'list'
because of the nested lists I guess?
How do I fix this?

>>> l = [[1, 2, 3], [5, 6, 7]]
>>> [[e*e for e in m] for m in l]
|-nested list-|
|---- complete list ---|
[[1, 4, 9], [25, 36, 49]]

Assuming you wanted the answer to look like this:
[[1, 4, 9], [25, 36, 49]]
You could do something like this:
l = [[1, 2, 3], [5, 6, 7]]
for x in range(len(l)):
for y in range(len(l[x])):
l[x][y] = l[x][y] * l[x][y]
print l
Obviously, the list comprehension answer is better.

[[1,2,3],[4,5,6]] != [1,2,3,4,5,6]
[map(lambda x: x *x,sl) for sl in l] #List comprhension

What you need is a recursive function, something like this:
def square(el):
if type(el) == list:
return [square(x) for x in el]
else:
return el**2;
I'd rather not get into the correctness of type(el) == list here, but you get the gist.
Of course, this is also doable with a list-comprehension, as many people have pointer out, provided that the structure is always the same. This recursive function can handle any level of recursion, and lists containing both lists and numbers.

Related

mapping the append function to a list

I want to do the following elegantly. I have a list:
list1 = [[1,2],[3,1,4,7],[5],[7,8]]
I'd like to append the number 1 to each element of the list, so that I have
list1 = [[1,2,1],[3,1,4,7,1],[5,1],[7,8,1]]
I'm trying to map this via
map(list.append([1]), vectors)
but this returns the error append() takes exactly one argument (0 given) and if I just try append([1]) (without list.), I get NameError: global name 'append' is not defined. I guess I could do it with a loop, but this seems more elegant, is there a way to map this correctly?
Here is a several ways to implement what you want:
More readable and classic way
for el in list1:
el.append(1)
List comprehension
list1 = [el + [1] for el in list1]
Generators:
list1 = (el + [1] for el in list1)
Map
list1 = map(lambda el: el + [1], list1)
What to use?
It depends on you own situation and may depends on execution speed optimizations, code readability, place of usage.
Map is a worst choice in case of readability and execution speed
For is a fastest and more plain way to do this
Generators allows you to generate new list only when you really need this
List comprehension - one liner for classic for and it takes advantage when you need quickly filter the new list using if
i.e. if you need only add element to each item - for loop is a best choice to do this, but if you need add item only if item > 40, then you may consider to use List comprehension.
For example:
Classic For
x = 41
for el in list1:
if x > 40:
el.append(x)
List comprehension
x = 1
list1 = [el + [x] for el in list1 if x > 40]
as #jmd_dk mentioned, in this sample is one fundamental difference: with simple for you can just append to an existing object of the list which makes much less impact to execution time and memory usage. When you use List comprehension, you will get new list object and in this case new list object for each item.
Try a list comprehension, taking advantage of the fact the adding lists concats them together.
new_list = [l + [1] for l in list1]
You can simply do
list1 = [[1,2],[3,1,4,7],[5],[7,8]]
for el in list1:
el.append(1)
map(lambda x: x + [1], list1)
you mean this?
list.append() have NO return (mean always return None)
With list comprehension and append, you can do:
list1 = [[1, 2], [3, 1, 4, 7], [5], [7, 8]]
[item.append(1) for item in list1]
print(list1) # Output: [[1, 2, 1], [3, 1, 4, 7, 1], [5, 1], [7, 8, 1]]
Output:
>>> list1 = [[1, 2], [3, 1, 4, 7], [5], [7, 8]]
>>> [item.append(1) for item in list1]
[None, None, None, None]
>>> list1
[[1, 2, 1], [3, 1, 4, 7, 1], [5, 1], [7, 8, 1]]
You may also use extend like this:
[item.extend([1]) for item in list1]
print(list1) # Output: [[1, 2, 1], [3, 1, 4, 7, 1], [5, 1], [7, 8, 1]]

Convert list of lists to list of integers

I need to convert a list of lists to a list of integers.
from:
L1 = [[1, 2, 3, 4], [3, 7, 1, 7], [0, 5, 6, 7], [9, 4, 5, 6]]
to:
L2 = [1234, 3717, 0567, 9456]
How can I make python recognize an integer starting with 0? Like the case L2[2]
The other question is, how can I check if items in a list are ordered?
A = [1, 2, 6, 9] ---->True
Other than this:
A == sorted(A)
You guys are FAST. Thanks!
The first question can be done by
L = [int("".join([str(y) for y in x])) for x in L]
Unfortunately, integers do not start with a 0. There is no way to do this.
Checking if A == sorted(A) is a perfectly fine way to do this.
L2 = [reduce(lambda x,y : 10 * x + y, l) for l in L1]
If you want a solution that doesn't go through strings.
For question 1, maybe Python 3 converts, but the plain .join give me a TypeError in Python 2. Try:
["".join(str(d) for d in x) for x in L]
...for the string representation, or
[int("".join(str(d) for d in x)) for x in L]
(The string representation is the only way to preserve leading zeros, except with formatted output...and then that's just string conversion on the way to the output file/string.)
For question 2: all(A[i-1] < A[i] for i in range(1, len(A)))
>>> A = [1, 2, 6, 9]
>>> all(A[i-1] < A[i] for i in range(1, len(A)))
True
You can do:
L2 = [ int("1" + "".join(str(l) for l in ll1)) for ll1 in L1 ]
to keep the zeros and get:
[11234, 13717, 10567, 19456]
but then you need to get rid of the leftmost 1s.

putting individual lists on new lines

Bloody stupid question from dead brain...
I have a list:
[1,2,3,4,5,6,7,8,9]
which I sliced up into 3 lists:
splits = [1,2,3],[4,5,6],[7,8,9]
which I would like to now have printed on individual lines such that
print splits
gives
[1,2,3]
[4,5,6]
[7,8,9]
Can someone please 1) whack me upside the head and 2) remind me how to do this?
If
s = [[1,2,3],[4,5,6],[7,8,9]] # list of lists
or
s = [1,2,3],[4,5,6],[7,8,9] # a tuple of lists
then
for i in s:
print(i)
will result in:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
Guided by the Zen of Python: Simple is better than complex.
Is the 3 lists a list of lists? ex [[1],[2],[3]]?
if so, just:
for sliced_list in list_of_lists:
print(sliced_list)
With your given syntax [1,2,3],[4,5,6],[7,8,9], it is a tuple of lists , which will behave the same when using the for statement.
Use the string join function:
print '\n'.join(str(x) for x in [[1,2,3],[4,5,6],[7,8,9]])
I do not understand your first quesion.
For the second one, you might like to do it like:
>>> splits = [1,2,3],[4,5,6],[7,8,9]
>>> print "\n".join([repr(item) for item in splits])
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]

Rearrange a python list into n lists, by column

I want to rearrange a list l into a list of n lists, where n is the number of columns.
e.g.,
l = [1,2,3,4,5,6,7,8,9,10]
n = 4
==> [[1,5,9],[2,6,10],[3,7][4,8]]
Can someone please help me out with an algorithm? Feel free to use any python awesomeness that's available; I'm sure theres some cool mechanism that's a good fit for this, i just can't think of it.
PS The example list just happened to be ordered numbers starting at 1. That's not my actual scenario.
There is indeed a cool mechanism for this in Python: the three-argument form of slicing, where the last argument is step size.
>>> l = [1,2,3,4,5,6,7,8,9,10]
>>> n = 4
>>> [l[i::n] for i in range(n)]
[[1, 5, 9], [2, 6, 10], [3, 7], [4, 8]]
l = [1,2,3,4,5,6,7,8,9,10]
n = 4
def f(l,n):
A = []
[A.append([]) for i in xrange(n)]
[ A [(i - 1) % n].append(i) for i in l]
return A
print f(l,n)
[[1, 5, 9], [2, 6, 10], [3, 7], [4, 8]]
The following function does what you want to achieve:
def rearrange(seq,n):
return [[v for i,v in enumerate(seq[x:]) if i%n==0] for x in xrange(len(seq))][:n]
Writing Python isn't a game of code golf, don't be afraid to use more than one line for the sake of readability.
l = [1,2,3,4,5,6,7,8]
def split_into_columns(input_list, num_of_cols=3):
retval = [ [] for _ in xrange(num_of_cols)] # build 3 columns
for i in xrange(len(input_list)): # iterate through original list
retval[i%num_of_cols].append(input_list[i]) # place in the "modulo 3" column
return retval
# here's a compressed, less readable version of that for-loop
#[retval[i%3].append(input_list[i]) for i in xrange(len(input_list))]
#return retval
print split_into_columns(l, 3)

Modifying list contents in Python

I have a list like:
list = [[1,2,3],[4,5,6],[7,8,9]]
I want to append a number at the start of every value in the list programmatically, say the number is 9. I want the new list to be like:
list = [[9,1,2,3],[9,4,5,6],[9,7,8,9]]
How do I go about doing this in Python? I know it is a very trivial question but I couldn't find a way to get this done.
for sublist in thelist:
sublist.insert(0, 9)
don't use built-in names such as list for your own stuff, that's just a stupid accident in the making -- call YOUR stuff mylist or thelist or the like, not list.
Edit: as the OP aks how to insert > 1 item at the start of each sublist, let me point out that the most efficient way is by assignment of the multiple items to a slice of each sublist (most list mutators can be seen as readable alternatives to slice assignments;-), i.e.:
for sublist in thelist:
sublist[0:0] = 8, 9
sublist[0:0] is the empty slice at the start of sublist, and by assigning items to it you're inserting the items at that very spot.
>>> someList = [[1,2,3],[4,5,6],[7,8,9]]
>>> someList = [[9] + i for i in someList]
>>> someList
[[9, 1, 2, 3], [9, 4, 5, 6], [9, 7, 8, 9]]
(someList because list is already used by python)
Use the insert method, which modifies the list in place:
>>> numberlists = [[1,2,3],[4,5,6]]
>>> for numberlist in numberlists:
... numberlist.insert(0,9)
...
>>> numberlists
[[9, 1, 2, 3], [9, 4, 5, 6]]
or, more succintly
[numberlist.insert(0,9) for numberlist in numberlists]
or, differently, using list concatenation, which creates a new list
newnumberlists = [[9] + numberlist for numberlist in numberlists]
If you're going to be doing a lot of prepending,
perhaps consider using deques* instead of lists:
>>> mylist = [[1,2,3],[4,5,6],[7,8,9]]
>>> from collections import deque
>>> mydeque = deque()
>>> for li in mylist:
... mydeque.append(deque(li))
...
>>> mydeque
deque([deque([1, 2, 3]), deque([4, 5, 6]), deque([7, 8, 9])])
>>> for di in mydeque:
... di.appendleft(9)
...
>>> mydeque
deque([deque([9, 1, 2, 3]), deque([9, 4, 5, 6]), deque([9, 7, 8, 9])])
*Deques are a generalization of stacks and queues (the name is pronounced "deck" and is short for "double-ended queue"). Deques support thread-safe, memory-efficient appends and pops from either side of the deque with approximately the same O(1) performance in either direction.
And, as others have mercifully mentioned:
For the love of all things dull and ugly,
please do not name variables after your favorite data-structures.
#!/usr/bin/env python
def addNine(val):
val.insert(0,9)
return val
if __name__ == '__main__':
s = [[1,2,3],[4,5,6],[7,8,9]]
print map(addNine,s)
Output:
[[9, 1, 2, 3], [9, 4, 5, 6], [9, 7, 8, 9]]

Categories