Iterating through a nested Leftsequence - python

I just wondered how can you iterate through a nested Leftsequence?
I made a left sequence out with the following code:
def leftSeq(s):
ls = "leer"
for i in range(len(s), 0, -1):
ls = (l[i - 1], ls)
return ls
l = [1,2,3]
Output = (1, (2, (3, 'leer')))
How do I iterate through it?

You could make an iterator for such left sequences:
def left_iterator(lseq):
while isinstance(lseq,tuple) and len(lseq) == 2:
first, lseq = lseq
yield first
yield lseq
#test:
x = (1, (2, (3, 'leer')))
for i in left_iterator(x):
print(i)
Output:
1
2
3
leer

You could use a while loop like so and nest through ls:
x = (1, (2, (3, 'leer'))) #=leftSeq(l)
while len(x) > 1:
print(x)
x = x[1]
(1, (2, (3, 'leer')))
(2, (3, 'leer'))
(3, 'leer')
leer

Related

Is there a pythonic way to iterate over two lists one element at a time?

I have two lists: [1, 2, 3] and [10, 20, 30]. Is there a way to iterate moving one element in each list in each step? Ex
(1, 10)
(1, 20)
(2, 20)
(2, 30)
(3, 30)
I know zip moves one element in both lists in each step, but that's not what I'm looking for
Is it what you expect:
def zip2(l1, l2):
for i, a in enumerate(l1):
for b in l2[i:i+2]:
yield (a, b)
>>> list(zip2(l1, l2))
[(1, 10), (1, 20), (2, 20), (2, 30), (3, 30)]
def dupe(l):
return [val for val in l for _ in (0,1)]
list(zip(dupe([1,2,3]), dupe([10,20,30])[1:]))
# [(1, 10), (1, 20), (2, 20), (2, 30), (3, 30)]
One with zip and list comprehension.
For good measure, here's a solution that works with arbitrary iterables, not just indexable sequences:
def frobnicate(a, b):
ita, itb = iter(a), iter(b)
flip = False
EMPTY = object()
try:
x, y = next(ita), next(itb)
yield x, y
except StopIteration:
return
while True:
flip = not flip
if flip:
current = y = next(itb, EMPTY)
else:
current = x = next(ita, EMPTY)
if current is EMPTY:
return
yield x, y

How can I remove parentheses (both side) from tuple?

This is my script.py:
from itertools import product
A = input().split()
B = input().split()
li1 = []
li2 = []
for i in A:
li1.append(int(i))
for j in B:
li2.append(int(j))
result = product(li1,li2)
print(tuple(result))
it gives me result like this ((1, 3), (1, 4), (2, 3), (2, 4))
But I want to result like this (1, 3) (1, 4) (2, 3) (2, 4)
How can I do this ?
Unpack with a *
print(*result)
This will use the contents of the iterable as arguments to print(), instead of the whole thing as a single argument.

How can i get sum of each elements in tuple Python

For example i have a tuple
t = ((1, 1), (1, 1), (1, 1))
How can i get sum of all this elements with only one loop
I would like to get
6
You can map with sum, and get the sum of the result:
sum(map(sum, t))
# 6
Or if you prefer it with a for loop:
res = 0
for i in t:
res += sum(i)
print(res)
# 6
You can use simple iteration (works in python3.8, I assume it works on older versions as well).
t = ((1, 1), (1, 1), (1, 1))
sum_tuples = 0
for a,b in t:
sum_tuples += a # First element
sum_tuples += b # Second Element
print(sum_tuples) # prints 6
You could use itertools.chain
>>> import itertools
>>> t = ((1, 1), (1, 1), (1, 1))
>>> sum(itertools.chain.from_iterable(t))
6
You can loop tuple to sum all. This code is long but it can sum tuple in tuple.
t = ((1, 1), (1, 1), (1, 1))
# Tuple in tuple:
t = ((1, 1, (1, 1, (1, 1))))
def getsum(var, current = 0):
result = current
if type(var) == tuple:
for i in range(len(var)):
x = var[i]
result = getsum(x, result)
else:
result += var
return result
print(getsum(t))

get indexes of elements from a zigzag configuration

"How could I get the indexes of elements in an n-row array configuration?
The length of a row should be given by a string of length l.
For example:
For a 2-row array configuration with l=7, the elements (X) will have indexes:
elements = [(0, 0), (0, 2), (0, 4), (0, 6), (1, 1), (1, 3), (1, 5), (1, 7)]
[[X - X - X - X],
[- X - X - X -]]
For a 3-rows array with l=8, the elements (X) will have indexes:
elements = [(0, 0), (0, 4), (0, 8), (1, 1), (1, 3), (1, 5), (1, 7), (2, 2), (2, 6)]
[[X - - - X - - - X],
[- X - X - X - X -],
[- - X - - - X - -]]
The idea is to extended to higher row numbers. Is there an "analytical" way of getting those indexes?
Thanks in advance.
P.S.: By "analytical" I mean an equation or something that I could code
this is my first shot at your problem:
def grid(width, depth):
assert depth % 2 == 0
height = depth//2 + 1
lines = []
for y in range(height):
line = ''.join('X' if ((i+y) % depth == 0 or (i-y) % depth == 0)
else '-' for i in range(width))
lines.append(line)
return '\n'.join(lines)
the depth is the parameter that defines how far the Xs are spaces on fhe first line (the name is poorly chosen); the width is how many characters should be displayed per line.
this will only work for even depths.
with outputs
-> print(grid(width=10, depth=2))
X-X-X-X-X-
-X-X-X-X-X
-> print(grid(width=10, depth=4))
X---X---X-
-X-X-X-X-X
--X---X---
-> print(grid(width=15, depth=6))
X-----X-----X--
-X---X-X---X-X-
--X-X---X-X---X
---X-----X-----
this was mostly trial & error so there is not much to explain...
if you prefer your elements representation - here is what you can do:
def grid_elements(width, depth):
assert depth % 2 == 0
height = depth//2 + 1
elements = []
for y in range(height):
elements.extend((y, i) for i in range(width)
if ((i+y) % depth == 0 or (i-y) % depth == 0))
return elements
this creates the results:
-> print(grid_elements(width=10, depth=2))
[(0, 0), (0, 2), (0, 4), (0, 6), (0, 8), (1, 1), (1, 3), (1, 5), (1, 7), (1, 9)]
-> print(grid_elements(width=10, depth=4))
[(0, 0), (0, 4), (0, 8), (1, 1), (1, 3), (1, 5), (1, 7), (1, 9), (2, 2), (2, 6)]
-> print(grid_elements(width=15, depth=6))
[(0, 0), (0, 6), (0, 12), (1, 1), (1, 5), (1, 7), (1, 11), (1, 13), (2, 2),
(2, 4), (2, 8), (2, 10), (2, 14), (3, 3), (3, 9)]
This is a example of code that can do this.
import numpy as np
nb_row = 3; nb_column = 10;
separator_element = '-'; element = 'X';
#Initialise the size of the table
table = np.chararray((nb_row, nb_column), itemsize=1);
table[:] = separator_element; #By default, all have the separator element.
#Loop over each column: First column have element at first row. The element
#will after decrease and wrap around the nb of row.
#When at the bottom, switch to go up. At top, switch to go down.
position_element = 0; go_down = 1;
for no_column in xrange(0,nb_column):
table[position_element,no_column] = element;
#Case when go down.
if go_down == 1:
position_element = (position_element+1) % (nb_row);
go_down = (position_element != (nb_row-1)); #Go up after go down.
#Case when go up;
else:
position_element = (position_element-1) % (nb_row);
go_down = (position_element == 0); #Go up after go down.
#end
#end
print(table)
#[['X' '-' '-' '-' 'X' '-' '-' '-' 'X' '-']
#['-' 'X' '-' 'X' '-' 'X' '-' 'X' '-' 'X']
#['-' '-' 'X' '-' '-' '-' 'X' '-' '-' '-']]
We can use itertools.groupby here to create a dictionary that has the
sublist indexes of interest as values and index of sublists as keys {0: [0, 2, 4, 6], 1: [1, 3, 5, 7]}, We can then use this on list that is generated using n = 7. From there we can modify the sublist using the indexes that are values for the corresponding sublist index in our keys.
from itertools import groupby
elements = [(0, 0), (0, 2), (0, 4), (0, 6), (1, 1), (1, 3), (1, 5), (1, 7)]
n = 7
d = {}
for k, g in groupby(elements, key=lambda x: x[0]):
d[k] = [i[1] for i in g]
lst = [['-']*n for i in d]
for k in d:
for i, v in enumerate(lst[k]):
if i in d[k]:
lst[k][i] = 'X'
lst[k] = ' '.join(lst[k])
for i in lst:
print(i)
# X - X - X - X
# - X - X - X -

Sort out pairs with same members but different order from list of pairs

From the list
l =[(3,4),(2,3),(4,3),(3,2)]
I want to sort out all second appearances of pairs with the same members in reverse order. I.e., the result should be
[(3,4),(2,3)]
What's the most concise way to do that in Python?
Alternatively, one might do it in a more verbose way:
l = [(3,4),(2,3),(4,3),(3,2)]
L = []
omega = set([])
for a,b in l:
key = (min(a,b), max(a,b))
if key in omega:
continue
omega.add(key)
L.append((a,b))
print(L)
If we want to keep only the first tuple of each pair:
l =[(3,4),(2,3),(4,3),(3,2), (3, 3), (5, 6)]
def first_tuples(l):
# We could use a list to keep track of the already seen
# tuples, but checking if they are in a set is faster
already_seen = set()
out = []
for tup in l:
if set(tup) not in already_seen:
out.append(tup)
# As sets can only contain hashables, we use a
# frozenset here
already_seen.add(frozenset(tup))
return out
print(first_tuples(l))
# [(3, 4), (2, 3), (3, 3), (5, 6)]
This ought to do the trick:
[x for i, x in enumerate(l) if any(y[::-1] == x for y in l[i:])]
Out[23]: [(3, 4), (2, 3)]
Expanding the initial list a little bit with different orderings:
l =[(3,4),(2,3),(4,3),(3,2), (1,3), (3,1)]
[x for i, x in enumerate(l) if any(y[::-1] == x for y in l[i:])]
Out[25]: [(3, 4), (2, 3), (1, 3)]
And, depending on whether each tuple is guaranteed to have an accompanying "sister" reversed tuple, the logic may change in order to keep "singleton" tuples:
l = [(3, 4), (2, 3), (4, 3), (3, 2), (1, 3), (3, 1), (10, 11), (10, 12)]
[x for i, x in enumerate(l) if any(y[::-1] == x for y in l[i:]) or not any(y[::-1] == x for y in l)]
Out[35]: [(3, 4), (2, 3), (1, 3), (10, 11), (10, 12)]
IMHO, this should be both shorter and clearer than anything posted so far:
my_tuple_list = [(3,4),(2,3),(4,3),(3,2)]
set((left, right) if left < right else (right, left) for left, right in my_tuple_list)
>>> {(2, 3), (3, 4)}
It simply makes a set of all tuples, whose members are exchanged beforehand if first member is > second member.

Categories

Resources