Reputation: 125
I'm trying to convert a line of Python code to JavaScript, but I have limited Python knowledge and struggle to make sense of it.
Can anyone please try to explain the following line of code? The point_orientation
function is not important, it just returns True/False.
i_extend = next( ( i for i in itertools.chain(range(i_start+1, len(p)), range(0,i_start+1)) if not point_orientation( p[i-1], p[i], p[(i+1) % len(p)] ) ) )
Upvotes: 0
Views: 1884
Reputation: 532093
chain
stitches two iterators together into one. Here, it's being used to help simulate a closed cycle starting at a particular point. Observe that
range(0, len(p)) == chain(range(0, i_start+1), range(i_start+1, len(p))
The given code swaps the arguments to chain
, so that it converts a sequence like [0,1,2,...,10]
into a sequence like [5,6,...,10,0,1,...,4]
. The three arguments to the predicate are just adjacent items in the cycle, with (i+1) % len(p)
doing the wrapping around at the end of the sequence. next
is just used to get the first element of the resulting sequence.
If you gave up on trying to express this in a one-liner, you might write the more understandable code that follows:
n = len(p)
for i in range(i_start + 1, i_start + 1 + n):
index_before = (i - 1) % n
index_at = i % n
index_after = (i+1) % n
if not point_orientation(p[index_before], p[index_at], p[index_after])
i_extend = y
break
We iterate over a single range, and do modular arithmetic on the each index inside the loop. If the predicate passes, we set i_extend
to the current point and break out. Otherwise, we continue the iteration, under the assumption that one of the points will eventually succeed.
Upvotes: 1
Reputation: 36043
It means "find the first element i
in range(i_start+1, len(p))
or range(0,i_start+1)
(if the first range doesn't have one) such that point_orientation( p[i-1], p[i], p[(i+1) % len(p)] )
is false". If there is no such i
, it will raise an exception.
Here it is in more verbose Python:
def check(i):
return point_orientation(p[i - 1],
p[i],
p[(i + 1) % len(p)])
def find_i_extend():
for i in range(i_start + 1, len(p)):
if not check(i):
return i
for i in range(0, i_start + 1):
if not check(i):
return i
i_extend = find_i_extend()
Upvotes: 2