Python 2.x: Summing items in a list of tuples - list

For summation purposes, I created a list of tuples, where multiple items in the list have the same first variable.
for example:
x = [('m32',[1,2,3]),('m32',[2,3,4]),('m32',[4,5,6]),('m33',[1,2,3]),('m33',[2,3,4]),('m33',[4,5,6]),('m34',[1,2,3]),('m34',[2,3,4]),('m34',[4,5,6])....]
I want to add the individual values of the second items in the tuples (i.e 1+2+4, 2+3+5, 3+4+6) for all values that have the same first item (i.e. 'm32').
In other words, for all items labeled 'm32', I want to be able to add the other values.
How can I slice/index this to loop through and perform the summation?

Some tricky zip magic, along with itertools.groupby to group the matching first items together:
>>> x = [('m32',[1,2,3]),('m32',[2,3,4]),('m32',[4,5,6]),('m33',[1,2,3]),('m33',[2,3,4]),('m33',[4,5,6]),('m34',[1,2,3]),('m34',[2,3,4]),('m34',[4,5,6])]
>>> from itertools import groupby
>>> from operator import itemgetter
>>> for k,g in groupby(x,key=itemgetter(0)):
... print (k,[sum(i) for i in zip(*zip(*g)[1])])
...
('m32', [7, 10, 13])
('m33', [7, 10, 13])
('m34', [7, 10, 13])
A breakdown of how it works:
g is the group of items with matching keys. zip(*g) transposes the matrix, bringing the keys and values together:
>>> for k,g in groupby(x,key=itemgetter(0)):
... print zip(*g)
...
[('m32', 'm32', 'm32'), ([1, 2, 3], [2, 3, 4], [4, 5, 6])]
[('m33', 'm33', 'm33'), ([1, 2, 3], [2, 3, 4], [4, 5, 6])]
[('m34', 'm34', 'm34'), ([1, 2, 3], [2, 3, 4], [4, 5, 6])]
Getting the 2nd items:
>>> for k,g in groupby(x,key=itemgetter(0)):
... print zip(*g)[1]
...
([1, 2, 3], [2, 3, 4], [4, 5, 6])
([1, 2, 3], [2, 3, 4], [4, 5, 6])
([1, 2, 3], [2, 3, 4], [4, 5, 6])
Transposing again to match up the items to sum:
>>> for k,g in groupby(x,key=itemgetter(0)):
... print zip(*zip(*g)[1])
...
[(1, 2, 4), (2, 3, 5), (3, 4, 6)]
[(1, 2, 4), (2, 3, 5), (3, 4, 6)]
[(1, 2, 4), (2, 3, 5), (3, 4, 6)]
And adding them up:
>>> for k,g in groupby(x,key=itemgetter(0)):
... print [sum(i) for i in zip(*zip(*g)[1])]
...
[7, 10, 13]
[7, 10, 13]
[7, 10, 13]

The answer given by Mark is great, and probably much more efficient that the one I'll post you. But I still want to post my answer because you are probably new to python and it will be easy for you to understand it.
For this kind of scripts you only need some imagination and basic python notions:
dictionary={}
for name, numbers in x:
if name in dictionary:
current_list=dictionary[name]
for i in range(3):
current_list[i]+=numbers[i]
else:
dictionary[name]=numbers
print(dictionary)
Note that the output is a dictionary:
{'m32': [7, 10, 13], 'm33': [7, 10, 13]}..
I hope it help you!

Related

Zipp lists in python by iterating through a list of lists

I have two lists of lists as follows. To merge them, I usually do the following:
>>>from itertools import imap, ilist
>>>a = [1,2,3]
>>>b = [4,5,6]
>>> c = list(imap(list,izip(a,b)))
>>> c
[[1, 4]], [2, 5], [3, 6]]
However, now I have a list of list as follows:
[[1,2,3],
[4,5,6],
[7,8,9],
]
How do I iterate through each list and pass it to the izip function to obtain the following output:
[[1,4,7],[2,5,8],[3,6,9]]
Answer for edited Question:
>>> input_list=[[1,2,3],
[4,5,6],
[7,8,9],
]
Using map and zip:
>>> map(list,zip(*input_list))
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
Using imap and izip:
>>> list(imap(list,list(izip(*input_list))))
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
Answer for previous question:
By using list comprehension and two for loops:
input_list =[[[1],[2],[3]],
[[4],[5],[6]],
[[7],[8],[9]],
]
out_list = [[] for i in range(len(input_list))]
for each_row in input_list:
for i in range(len(each_row)):
out_list[i].extend(each_row[i])
print out_list
Output:
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
I think u need something like this:
input_list =[[1,2,3],
[4,5,6],
[7,8,9],
]
result = []
for i in range(len(input_list)):
temp = []
for list in input_list:
temp.append(list[i])
result.append(temp)
print result
result will be:
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]

Skipping list of lists elements

I have this nested list:
list = [[1, 2, 3, 4],
[2, 7, 2, 1],
[3, 3, 7, 5],
[4, 4, 1, 7]]
And I'm trying to skip the first list of this nested list, and the first element of each list. I want it to become like this:
list = [[7, 2, 1],
[3, 7, 5],
[4, 1, 7]]
So far I have this:
% skip first list in list of lists
skip_first_list([_|Tail], Tail).
% attemping to skip first element in each of the lists
skip_first_list([[_ | HeadTail] | Tail], X) :-
skip_first_list(Tail, R),
append(R, [HeadTail], X).
Which does not produce the correct result:
?- skip_first_list([[1, 2, 3, 4], [2, 7, 2, 1], [3, 3, 7, 5], [4, 4, 1, 7]], X).
X = [[2, 7, 2, 1], [3, 3, 7, 5], [4, 4, 1, 7]] ;
X = [[3, 3, 7, 5], [4, 4, 1, 7], [2, 3, 4]] ;
X = [[4, 4, 1, 7], [7, 2, 1], [2, 3, 4]] ;
X = [[3, 7, 5], [7, 2, 1], [2, 3, 4]] ;
false.
Whereas I'm after this answer:
X = [[7, 2, 1], [3, 7, 5], [4, 1, 7]]
My result so far seems to be showing I'm appending in a reverse/incorrect order, How can I fix this? I don't really understand what order Prolog evaluates expressions. Any any would be appreciated.
Well the specification is that you provide a list of lists and that:
the first sublist is ignored (not part of the output); and
that for the remaining sublists, all heads are ignored as well.
So we better split this into two predicates:
remove_heads/2, which removes the heads of all sublists; and
remove_upper_left/2 which remove the first sublist, and then uses the above predicate to pop the heads of the sublists.
We can perform remove_heads/2 for instance with recursion:
remove_heads([],[]).
remove_heads([[_|H]|T],[H|T2]) :-
remove_heads(T,T2).
finally our remove_upper_left/2 simply ignores the head of the list, and makes a call to remove_heads with the tail:
remove_upper_left([_|T],T2) :-
remove_heads(T,T2).
Or in full:
remove_heads([],[]).
remove_heads([[_|H]|T],[H|T2]) :-
remove_heads(T,T2).
remove_upper_left([_|T],T2) :-
remove_heads(T,T2).
This then produces:
?- remove_upper_left([[1, 2, 3, 4], [2, 7, 2, 1], [3, 3, 7, 5], [4, 4, 1, 7]],X).
X = [[7, 2, 1], [3, 7, 5], [4, 1, 7]].
and works in the opposite direction as well:
?- remove_upper_left(X, [[1, 2, 3, 4], [2, 7, 2, 1], [3, 3, 7, 5], [4, 4, 1, 7]]).
X = [_G1364, [_G1370, 1, 2, 3, 4], [_G1376, 2, 7, 2, 1], [_G1382, 3, 3, 7, 5], [_G1388, 4, 4, 1|...]].
So here it prepends a variable to every list, and prepends a variable (possibly a sublist) to the output.
Furthermore we have here two predicates at the price of one: we can also use remove_heads/2 in the future if we want to pop the heads of all the sublists in a list of lists.

Create a function genSet() that takes in a list of numbers and returns a sorted set in python

I am new to python and trying to solve this example on pyschool
I need to write a function,
a) that takes a list of numbers
b) removes duplicates from the list
c) returns a sorted set:
In python, example :
>>> genSet([5,4,8,4,9,8])
[4, 5, 8, 9 ]
>>> genSet([3,-2,-1,-1,3,-2,0])
[-2, -1, 0, 3 ]
Removing Duplicates:
>>> t = [1, 2, 3, 1, 2, 5, 6, 7, 8]
>>> t
[1, 2, 3, 1, 2, 5, 6, 7, 8]
>>> list(set(t))
[1, 2, 3, 5, 6, 7, 8]
>>> s = [1, 2, 3]
>>> list(set(t) - set(s))
[8, 5, 6, 7]
Sort the List:
>>> sorted([5, 2, 3, 1, 4])
[1, 2, 3, 4, 5]
Now you could write your custom function, that removes duplicates and sort.
The following code snippet works:
def genSet(clist):
t = list(set(clist))
return sorted(t)
if __name__ == "__main__":
print genSet([5,4,8,4,9,8])
print genSet([3,-2,-1,-1,3,-2,0])
If you want to iterate over multiple list try this:
a = [
[5,4,8,4,9,8],
[3,-2,-1,-1,3,-2,0]
]
for aa in a:
print genSet(aa)
set will automatically remove duplicates and sorted will sort the list.
def genSet(l):
return (sorted(set(l)))

How to copy list items certain amount of times?

I have a big list of around 2000 numbers in the list. This is just an example of what I want.
I have list1=[1,2,3,4] and list2=[1,3,2,5]. I want it so that list1[i] will be used list2[i] times in the new list.
So for this example the new list would be:list3=[1,2,2,2,3,3,4,4,4,4,4]
The new list3 has 1x1, 3x2, 2x3, 5x4.
This isn't pretty and isn't particularly easy to understand, but works:
>>> list1 = [1, 2, 3, 4]
>>> list2 = [1, 3, 2, 5]
>>> import itertools
>>> list3 = list(itertools.chain(*[[list1[i]] * count for i, count in enumerate(list2)]))
>>> list3
[1, 2, 2, 2, 3, 3, 4, 4, 4, 4, 4]
Brief explanation...
You can multiply a list:
>>> [1] * 3
[1, 1, 1]
Using this in the list comprehension will get you a list-of-lists:
>>> [[list1[i]] * count for i, count in enumerate(list2)]
[[1], [2, 2, 2], [3, 3], [4, 4, 4, 4, 4]]
You can then use itertools to flatten the list as above.
list1=[1,2,3,4]
list2=[1,3,2,5]
list3 = []
for a, b in zip(list1, list2):
for i in range(b):
list3.append(a)
list3 == [1, 2, 2, 2, 3, 3, 4, 4, 4, 4, 4]
Another alternative:
list1=[1,2,3,4]
list2=[1,3,2,5]
z=[]
for x,y in zip(list1,list2):
z.extend([x] * y)
print z

How to select values 2+ after any number in a list?

Is there any way to select the second, third (etc) value from a value in a list in Groovy? I'm still very new to programming in general and am just wondering if there is an easy way to do this.
For example, if I have the list
[1, 2, 3, 4, 5, 6]
I want to select the next two values after each value using a for loop:
for 1: (1, 2, 3)
for 2: (2, 3, 4)
...and so on.
Is that easily possible? Thanks in advance!
If you're using groovy 1.8.1 or later, you can use the take and drop methods:
def foo = [1, 2, 3, 4, 5, 6]
foo.size().times { i ->
println foo.drop(i).take(3)
}
This will result in
[1, 2, 3]
[2, 3, 4]
[3, 4, 5]
[4, 5, 6]
[5, 6]
[6]
If you want the iteration to stop at the last group of three, try something like this:
def foo = [1, 2, 3, 4, 5, 6]
if (foo.size() > 2) {
(foo.size() - 2).times { i ->
println foo.drop(i).take(3)
}
}
which gives
[1, 2, 3]
[2, 3, 4]
[3, 4, 5]
[4, 5, 6]
If you're not using Groovy 1.8.1+, then you can acheive a similar result by writing a function like so:
List split( List foo, int size ) {
(0..foo.size()-size).collect { foo[ it..it+size-1 ] }
}
Then, you can call this like:
split( [1, 2, 3, 4, 5, 6], 3 )
to print
[[1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6]]