Iterating through list in python 2.7 - python

How will I do the following?
class a:
def get(self):
return (1, 2)
i = a() #this is variable that i wont have access directly and should be accessed only from list P below
P = [i, i, i, i]
Q = [P, P, P, P]
I want is
L = [list of all i.get() results iterating through Q and P]
for eg
L = [px.get() for px in P for P in Q] # I want something like this
i.e
L = [(1, 2), (1, 2), (1, 2), (1, 2), (1, 2), (1, 2), (1, 2), (1, 2), (1, 2), (1, 2), (1, 2), (1, 2), (1, 2), (1, 2), (1, 2), (1, 2)]

Use a list comprehension:
L = [i.get() for P in Q for i in P]
This gives you [Q[0][0].get(), Q[0][1].get(), ..., Q[-1][-2].get(), Q[-1][-1].get()]
The double loop is just like a nested for loop outside of a list comprehension, the above is the equivalent of:
L = []
for P in Q:
for i in P:
L.append(i.get())
The list comprehension follows the same order of loops, nesting is translated to loops being listed from left to right.

Replicating a list can be done with the * operator in Python (i.e. multiplying a list):
>>> [i.get()] * (len(P) + len(Q))
[(1,2), (1,2), (1,2), (1,2), (1,2), (1,2), (1,2), (1,2)]

Related

Program to get a sorted list in increasing order of last element in each tuple in a given list using decorators

I try to get execute a program to get a sorted list in increasing order of last element in each tuple in a given list using decorators.
Here is my decorator:->
import functools
List2 =[]
List3 =[]
def parapassing_decorator(tuple1):
def getSortedElement(func):
#functools.wraps(func)
def inner1(*args, **kwargs):
list2 = func(*args, **kwargs)
output = [ q for q in tuple1 for l in list2 if l == int(q[1],)]
print(output)
return inner1;
Now get the all last element from all tuples and sort it here
#parapassing_decorator(tuple1 = ([(2, 5), (1, 2), (4, 4), (2, 3), (2, 1)]))
def getlastelements(tuple1):
for t in tuple1:
List2.append(t)
List2.sort()
return List2
now decorator is passing with getlastelements function to compare with all tuples last elements and rearrange it in a list.
calling method:-
getlastelements(tuple1=[(2, 5), (1, 2), (4, 4), (2, 3), (2, 1)])
But I got the error like:-
35 #parapassing_decorator(tuple1 = ([(2, 5), (1, 2), (4, 4), (2, 3), (2, 1)]))
---> 36 def getlastelements(tuple1):
37 for t in tuple1:
38 List2.append(t)
TypeError: 'NoneType' object is not callable
Sorry for trouble you all.
I think this solution is usable.
import functools
List2 =[]
List3 =[]
def parapassing_decorator(tuple1):
#functools.wraps(tuple1)
def inner1(func):
list2 = func(tuple1)
output = [ q for l in list2 for q in tuple1 if l == int(q[1],)]
List3.append(output)
print(output)
return inner1;
#parapassing_decorator(tuple1 = ([(2, 5), (1, 2), (4, 4), (2, 3), (2, 1)]))
def getlastelements(x):
for t in x:
List2.append(t[1])
List2.sort()
return List2

I have to retun an array, not a linked list

Reference Diagram:
I have to return the array. So far I have written my code. But I am not sure if the return array matched with the diagram.
def return_shape():
list_1 = [(0, 2), None]
list_2 = [(1, 2), None]
list_3 = [(2, 2), None]
list_4 = [(3, 2), None]
list_5 = [(0, 1), list_1]
list_6 = [(1, 1), list_2]
list_7 = [(2, 1), list_3]
list_8 = [(3, 1), list_4]
list_9 = [(0, 0), list_5]
list_10 = [(1, 0), list_6]
list_11 = [(2, 0), list_7]
list_12 = [(3, 0), list_8]
list_13 = [None, list_12]
list_14 = [list_11, list_13]
list_15 = [list_10, list_14]
main_list = [list_9, list_15]
return main_list
This is a strange question. My first intuition would be to return a linked list.
Anyway, shouldn't you be returning [list_15, list_9]instead of [list_9, list_15] based on the order?
Tip: it would be better if you sticked to the same numbering convention. (e.g. left to write, increment from list 1 to list 4)

How do I impose a condition that must be satisfied by *any two* members of a set?

I want to use python to define one set in terms of another, as follows: For some set N that consists of sets, define C as the set such that an element n of N is in C just in case any two elements of n both satisfy some specific condition.
Here is the particular problem I need to solve. Consider the power set N of the set of ordered pairs of elements in x={1,2,3,4,5,6}, and the following subsets of N:
i = {{1,1},{2,2},{3,4},{4,3},{5,6},{6,5}}
j = {{3,3},{4,4},{1,2},{2,1},{5,6},{6,5}}
k = {{5,5},{6,6},{1,2},{2,1},{3,4},{4,3}}
Using python, I want to define a special class of subsets of N: the subsets of N such that any two of their members are both either in i, j, or k.
More explicitly, I want to define the set terms: C = {n in N| for all a, b in n, either a and b are both in i or a and b are both in j or a and b are both in k}.
I'm attaching what I tried to do in Python. But this doesn't give me the right result: the set C I'm defining here is not such that any two of its members are both either in i, j, or k.
Any leads would be much appreciated!
import itertools
def powerset(iterable):
s = list(iterable)
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
x = [1,2,3,4,5,6]
ordered_pairs = [[j,k] for j in x for k in x if k>=j]
powers = list(powerset(ordered_pairs))
i = [[1,1],[2,2],[3,4],[4,3],[5,6],[6,5]]
j = [[3,3],[4,4],[1,2],[2,1],[5,6],[6,5]]
k = [[5,5],[6,6],[1,2],[2,1],[3,4],[4,3]]
M = [i,j,k]
C = []
for n in powers:
for a in n:
for b in n:
for m in M:
if a in m:
if b in m:
if a != b:
C.append(n)
if len(n) == 1:
C.append(n)
First of all, note that the ordered pairs you list are sets, not pairs. Use tuples, since they're hashable, and you'll be able to easily generate the power set using itertools. With that done, you have an easier time identifying the qualifying subsets.
The code below implements that much of the process. You can accumulate the hits at the HIT line of code. Even better, you can collapse the loop into a nested comprehension using any to iterate over the three zone sets.
test_list = [
set(((1,1),(2,2))), # trivial hit on i
set(), # trivial miss
set(((1, 1), (4, 4), (6, 6))), # one element in each target set
set(((3, 3), (6, 2), (4, 4), (2, 2))), # two elements in j
]
i = set(((1,1),(2,2),(3,4),(4,3),(5,6),(6,5)))
j = set(((3,3),(4,4),(1,2),(2,1),(5,6),(6,5)))
k = set(((5,5),(6,6),(1,2),(2,1),(3,4),(4,3)))
zone = [i, j, k]
for candidate in test_list:
for target in zone:
overlap = candidate.intersection(target)
if len(overlap) >= 2:
print("HIT", candidate, target)
break
else:
print("MISS", candidate)
Output:
HIT {(1, 1), (2, 2)} {(5, 6), (4, 3), (2, 2), (3, 4), (1, 1), (6, 5)}
MISS set()
MISS {(4, 4), (1, 1), (6, 6)}
HIT {(6, 2), (3, 3), (4, 4), (2, 2)} {(1, 2), (3, 3), (5, 6), (4, 4), (2, 1), (6, 5)}

Python combinational algorithmic program to return sublist of a list

I am trying to write a program to return sublist of a list i.e. for a list [1,2,3], the program should return [1],[2],[3],[1,2],[2,3] and [1,2,3].
I know of the concept of dictionary as well apart from list. So, can somebody instruct me on how i can solve this problem so that I could implement the same concept in other similar problems?
There is an implementation here
from itertools import chain, combinations
def powerset(iterable):
xs = list(iterable)
# note we return an iterator rather than a list
return chain.from_iterable( combinations(xs,n) for n in range(len(xs)+1) )
>>> list(powerset([1,2,3]))
[(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)]
If you don't want the empty element:
>>> list(filter(lambda x: len(x) >= 1, powerset([1,2,3])))
[(1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)]

Accumulate items in a list of tuples

I have a list of tuples that looks like this:
lst = [(0, 0), (2, 3), (4, 3), (5, 1)]
What is the best way to accumulate the sum of the first and secound tuple elements? Using the example above, I'm looking for the best way to produce this list:
new_lst = [(0, 0), (2, 3), (6, 6), (11, 7)]
I am looking for a solution in Python 2.6
I would argue the best solution is itertools.accumulate() to accumulate the values, and using zip() to split up your columns and merge them back. This means the generator just handles a single column, and makes the method entirely scalable.
>>> from itertools import accumulate
>>> lst = [(0, 0), (2, 3), (4, 3), (5, 1)]
>>> list(zip(*map(accumulate, zip(*lst))))
[(0, 0), (2, 3), (6, 6), (11, 7)]
We use zip() to take the columns, then apply itertools.accumulate() to each column, then use zip() to merge them back into the original format.
This method will work for any iterable, not just sequences, and should be relatively efficient.
Prior to 3.2, accumulate can be defined as:
def accumulate(iterator):
total = 0
for item in iterator:
total += item
yield total
(The docs page gives a more generic implementation, but for this use case, we can use this simple implementation).
How about this generator:
def accumulate_tuples(iterable):
accum_a = accum_b = 0
for a, b in iterable:
accum_a += a
accum_b += b
yield accum_a, accum_b
If you need a list, just call list(accumulate_tuples(your_list)).
Here's a version that works for arbitrary length tuples:
def accumulate_tuples(iterable):
it = iter(iterable):
accum = next(it) # initialize with the first value
yield accum
for val in it: # iterate over the rest of the values
accum = tuple(a+b for a, b in zip(accum, val))
yield accum
>> reduce(lambda x,y: (x[0] + y[0], x[1] + y[1]), lst)
(11, 7)
EDIT. I can see your updated question. To get the running list you can do:
>> [reduce(lambda x,y: (x[0]+y[0], x[1]+y[1]), lst[:i]) for i in range(1,len(lst)+1)]
[(0, 0), (2, 3), (6, 6), (11, 7)]
Not super efficient, but at least it works and does what you want :)
This works for any length of tuples or other iterables.
from collections import defaultdict
def accumulate(lst):
sums = defaultdict(int)
for item in lst:
for index, subitem in enumerate(item):
sums[index] += subitem
yield [sums[index] for index in xrange(len(sums))]
print [tuple(x) for x in accumulate([(0, 0), (2, 3), (4, 3), (5, 1)])]
In Python 2.7+ you would use a Counter instead of defaultdict(int).
This is a really poor way (in terms of performance) to do this because list.append is expensive, but it works.
last = lst[0]
new_list = [last]
for t in lst[1:]:
last += t
new_list.append(last)
Simple method:
>> x = [(0, 0), (2, 3), (4, 3), (5, 1)]
>>> [(sum(a for a,b in x[:t] ),sum(b for a,b in x[:t])) for t in range(1,len(x)+1)]
[(0, 0), (2, 3), (6, 6), (11, 7)]
lst = [(0, 0), (2, 3), (4, 3), (5, 1)]
lst2 = [lst[0]]
for idx in range(1, len(lst)):
newItem = [0,0]
for idx2 in range(0, idx + 1):
newItem[0] = newItem[0] + lst[idx2][0]
newItem[1] = newItem[1] + lst[idx2][1]
lst2.append(newItem)
print(lst2)
You can use the following function
>>> def my_accumulate(lst):
new_lst = [lst[0]]
for x, y in lst[1:]:
new_lst.append((new_lst[-1][0]+x, new_lst[-1][1]+y))
return new_lst
>>> lst = [(0, 0), (2, 3), (4, 3), (5, 1)]
>>> my_accumulate(lst)
[(0, 0), (2, 3), (6, 6), (11, 7)]
Changed my code to a terser version:
lst = [(0, 0), (2, 3), (4, 3), (5, 1)]
def accumulate(the_list):
the_item = iter(the_list)
accumulator = next(the_item)
while True:
yield accumulator
accumulator = tuple(x+y for (x,y) in zip (accumulator, next(the_item)))
new_lst = list(accumulate(lst))

Categories