How to add columns in multiple lists? - python

In python,
y = [1,2,3,4]
[1,2,3,4]
[1,2,3,4]
[1,2,3,4]
Notice that y contains four lines of lists, and it is not a matrix.
What I am trying to do is to add last columns of fours and output:
[1,2,3,16]

Let us suppose that you have list of lists:
y = [[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]]
res = y[0][:3] + [sum(el[3] for el in y)]
print res
>>> [1, 2, 3, 16]

Related

How to pack consecutive duplicates of list elements into sublists?

How can I "pack" consecutive duplicated elements in a list into sublists of the repeated element?
What I mean is:
l = [1, 1, 1, 2, 2, 3, 4, 4, 1]
pack(l) -> [[1,1,1], [2,2], [3], [4, 4], [1]]
I want to do this problem in a very basic way as I have just started i.e using loops and list methods. I have looked for other methods but they were difficult for me to understand
For removing the duplicates instead of packing them, see Removing elements that have consecutive duplicates
You can use groupby:
from itertools import groupby
def pack(List):
result = []
for key, group in groupby(List):
result.append(list(group))
return result
l = [1, 1, 1, 2, 2, 3, 4, 4, 1]
print(pack(l))
Or one-line:
l = [1, 1, 1, 2, 2, 3, 4, 4, 1]
result = [list(group) for key,group in groupby(l)]
# [[1, 1, 1], [2, 2], [3], [4, 4], [1]]
You can use:
lst = [1, 1, 1, 2, 2, 3, 4, 4, 1]
# bootstrap: initialize a sublist with the first element of lst
out = [[lst[0]]]
for it1, it2 in zip(lst, lst[1:]):
# if previous item and current one are equal, append result to the last sublist
if it1 == it2:
out[-1].append(it2)
# else append a new empty sublist
else:
out.append([it2])
Output:
>>> out
[[1, 1, 1], [2, 2], [3], [4, 4], [1]]
This code will do:
data = [0,0,1,2,3,4,4,5,6,6,6,7,8,9,4,4,9,9,9,9,9,3,3,2,45,2,11,11,11]
newdata=[]
for i,l in enumerate(data):
if i==0 or l!=data[i-1]:
newdata.append([l])
else:
newdata[-1].append(l)
#Output
[[0,0],[1],[2],[3],[4,4],[5],[6,6,6],[7],[8],[9],[4,4],[9,9,9,9,9],[3,3],[2],[45],[2],[11,11,11]]

Incorrect List manipulation

Let's say
>>> a = [1,2,3,4,5]
And I want an output like
>>> b
[[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5]]
Here is my code:
class Child(object):
def get_lines(self):
a = [1,2,3,4,5]
b=[]
c=[]
j=0
for i in a:
print i
b.append(i)
print b
c.insert(j,b)
j=j+1
print c
son= Child()
son.get_lines()
When I print list b in loop, it gives:
1
[1]
2
[1, 2]
3
[1, 2, 3]
4
[1, 2, 3, 4]
5
[1, 2, 3, 4, 5]
and the output is:
[[1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5]]
Where do I make wrong in the code?
b is always the same list object (note I've changed print c to return c):
>>> map(id, Child().get_lines())
...
[49021616, 49021616, 49021616, 49021616, 49021616]
c contains five references to the same list. I think what you want is:
class Child(object):
def get_lines(self):
a = [1, 2, 3, 4, 5]
return [a[:x+1] for x in range(len(a))]
This makes a shallow copy of part (or all) of a for each step:
>>> Child().get_lines()
[[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5]]
Replace:
c.insert(j,b)
with:
c.append(b[:])
and try again.
You need to make a copy of b. Otherwise you add the same b again and again resulting in the full list at all indices. 'b[:]' copies the list.
This solution does the same but is a bit shorter:
a = [1, 2, 3, 4, 5]
c = []
for i in range(1, len(a) + 1):
c.append(a[:i])
now c is:
[[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5]]
a[:i] slices the list a from the beginning to excluding the index i.
In this case it does a[:1], a[:2] and so on. a[:1] makes a new list [1],
a[:2] a new list [1, 2,] and so on. Using append() is simpler and insert().
Another alternative is a list comprehension:
a = [1, 2, 3, 4, 5]
[a[:i] for i in range(1, len(a) + 1)]
also results in:
[[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5]]
Here in this case you are not supposed to append value to the list object (b).
since list is mutable, it will refer to the exact same object in memory until a reassign occurs.
>>> b=[]
>>> b.append(1)
>>> id(b)
4337935424
>>> b.append(2)
>>> id(b)
4337935424
>>> b.append(3)
>>> id(b)
4337935424
>>> b = [1, 2, 3, 4]
>>> id(b)
4337942608
so that in your code c will make five references to the same list.
It will instruct a new object and then (to the extent possible) inserts references into it to the objects found in the original.
>>> class Child(object):
...
... def get_lines(self):
... a = [1, 2, 3, 4, 5]
... return map(lambda x: a[:x+1], range(len(a)))
...
>>> Child().get_lines()
[[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5]]
You insert same b five times in list c. As a list actually contains references to objects and not copies, you have 5 times a reference to a same b list in which you have added successively 1, 2, 3, 4, 5. So the result.
You must instead add copies of list b :
def get_lines(self):
a = [1,2,3,4,5]
b=[]
c=[]
j=0
for i in a:
print i
b.append(i)
print b
c.insert(j,b[:]) # forces insertion of a copy
j=j+1
print c
In the loop, value of b persists since it's a mutable object. Hence when you print c, the last value of b is shown.
Instead of using b as temporary variable, you can directly use a as follows:
class Child(object):
def get_lines(self):
a = [1,2,3,4,5]
b = []
for index, element in enumerate(a, 1):
b.append(x[:index])
return b
son= Child()
son.get_lines()

Python, slicing lists?

i really need your help with slicing a list.
lets say I've got a list of lists like this:
field=[[1, 2, 4, 4], [4, 1, 4, 2], [2, 1, 4, 3], [2, 4, 2, 3], [1, 2, 3, 4]]
and I have to write a function which will return a string that will look like this:
42334
44423
21142
14221
thus fat i managed to do this:
def out(field):
b=''
for list in field:
list1=list[::-1]
b+=''.join((str(sth) for sth in list1))+'\n'
return b
which returns this:
4421
2414
3412
3242
4321
You need to transpose your list of rows to a list of columns, as well as reverse the results of the transposition to get a proper rotation.
zip(*field) transposes the rows to columns, reversed() then reverses the results. Combined with a list comprehension you can do this all in one expression:
def out(field):
return '\n'.join([''.join(map(str, c)) for c in reversed(list(zip(*field)))])
or spelled out into an explicit loop:
def out(field):
b = []
for columns in reversed(list(zip(*field))):
b.append(''.join(map(str, columns)))
return '\n'.join(b)
The list() call around the zip() call allows us to reverse the iterator result in Python 3; it can be dropped in Python 2.
Demo:
>>> field=[[1, 2, 4, 4], [4, 1, 4, 2], [2, 1, 4, 3], [2, 4, 2, 3], [1, 2, 3, 4]]
>>> [''.join(map(str, c)) for c in reversed(list(zip(*field)))]
['42334', '44423', '21142', '14221']
>>> '\n'.join([''.join(map(str, c)) for c in reversed(list(zip(*field)))])
'42334\n44423\n21142\n14221'
>>> print('\n'.join([''.join(map(str, c)) for c in reversed(list(zip(*field)))]))
42334
44423
21142
14221
def out(field):
b=''
a=[]
while len(field[0])>0:
for list in field:
a.append(list.pop())
a.append("\n")
a="".join(str(x) for x in a)
return a
x=[[1, 2, 4, 4], [4, 1, 4, 2], [2, 1, 4, 3], [2, 4, 2, 3], [1, 2, 3, 4]]
print out(x)

Splitting a list of arbitrary size into N-not-equal parts [duplicate]

This question already has answers here:
How to group a list of tuples/objects by similar index/attribute in python?
(3 answers)
Closed 8 years ago.
I see splitting-a-list-of-arbitrary-size-into-only-roughly-n-equal-parts. How about not-equal splitting? I have list having items with some attribute (value which can be retrieved for running same function against every item), how to split items having same attribute to be new list e.g. new sublist? Something lambda-related could work here?
Simple example could be:
list = [1, 1, 1, 2, 3, 3, 3, 3, 4, 4]
After fancy operation we could have:
list = [[1, 1, 1], [2], [3, 3, 3, 3], [4, 4]]
>>> L = [1, 1, 1, 2, 3, 3, 3, 3, 4, 4]
>>> [list(g) for i, g in itertools.groupby(L)]
[[1, 1, 1], [2], [3, 3, 3, 3], [4, 4]]
>>> L2 = ['apple', 'aardvark', 'banana', 'coconut', 'crow']
>>> [list(g) for i, g in itertools.groupby(L2, operator.itemgetter(0))]
[['apple', 'aardvark'], ['banana'], ['coconut', 'crow']]
You should use the itertools.groupby function from the standard library.
This function groups the elements in the iterable it receives (by default using the identity function, i.e., checking consequent elements for equality), and for each streak of grouped elements, it reutrns a 2-tuple consisting of the streak representative (the element itself), and an iterator of the elements within the streak.
Indeed:
l = [1, 1, 1, 2, 3, 3, 3, 3, 4, 4]
list(list(k[1]) for k in groupby(l))
>>> [[1, 1, 1], [2], [3, 3, 3, 3], [4, 4]]
P.S. you should avoid using list as a variable name, as it would conflict with the built-in type/function.
Here's a pretty simple roll your own solution. If the 'attribute' in question is simply the value of the item, there are more straightforward approaches.
def split_into_sublists(data_list, sizes_list):
if sum(sizes_list) != len(data_list):
raise ValueError
count = 0
output = []
for size in sizes_list:
output.append(data_list[count:count+size])
count += size
return output
if __name__ == '__main__':
data_list = [1, 1, 1, 2, 3, 3, 3, 3, 4, 4]
sizes_list = [3,1,4,2]
list2 = [[1, 1, 1], [2], [3, 3, 3, 3], [4, 4]]
print(split_into_sublists(data_list, sizes_list) == list2) # True

Repeat a list within a list X number of times

I'm working on a project and I need to repeat a list within a list a certain number of times. Obviously, L.append(L) just adds the elements again without creating separate lists. I'm just stumped on how to make the lists separate within the big list.
In short form, this is what I have:
L = [1,2,3,4,5]
If I wanted to to repeat it, say, 3 times so I'd have:
L = [[1,2,3,4,5],[1,2,3,4,5],[1,2,3,4,5]]
How do I achieve this? I'm looking for lists within the big list.
No need for any functions:
>>> L = [1,2,3,4,5]
>>> [L]*3
[[1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5]]
However, you should note that if you change one value in any of the lists, all the others will change because they reference the same object.
>>> mylist = [L]*3
>>> mylist[0][0] = 6
>>> print mylist
[[6, 2, 3, 4, 5], [6, 2, 3, 4, 5], [6, 2, 3, 4, 5]]
>>> print L
[6, 2, 3, 4, 5]
To avoid this:
>>> L = [1,2,3,4,5]
>>> mylist = [L[:] for _ in range(3)]
>>> mylist[0][0] = 6
>>> print L
[1, 2, 3, 4, 5]
>>> print mylist
[[6, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5]]
Notice how L didn't change, and only the first list in mylist changed.
Thanks everyone in the comments for helping :).

Categories