Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
108 views
in Technique[技术] by (71.8m points)

Slice a list based on an index and items behind it in Python

Say I have an array of degree values, like this:

DEGREES = [
    0, 15, 30, 45, 60,
    75, 90, 105, 120,
    135, 150, 165, 180,
    195, 210, 225, 240,
    255, 270, 285, 300,
    315, 330, 345,
]

I would pick an angle and then be able to bisect this hypothetical circle in order to make it easier to find the shortest route to the target direction.

Saying that, how can I pick a specific value, like 90, and then be able to find the previous 12 elements behind that, including the index wrapping around to the end?

So, taking that earlier value and applying to that list, I would get something like this:

[90, 75, 60, 45, 30, 15, 0, 345, 330, 315, 300, 285, 270]

Using slice notation, I tried doing this:

index = DEGREES.index(90)
print(DEGREES[index-12:index]) # start 12 values back, stop at index

But this only prints an empty array.

Is there a way to slice a list so I can get the 12 previous values behind the index I'm using?

EDIT:

This turned out to be an XY Problem, my bad. Originally, I was trying to create a smooth rotation system in Pygame, with my attempts to calculate angles not working, I asked this question to solve a problem with yet another idea I was trying to implement. I ended up accepting the answer that helped me set up the smooth rotation system, but there are relevant answers to the original question below that.

question from:https://stackoverflow.com/questions/56135864/slice-a-list-based-on-an-index-and-items-behind-it-in-python

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Arithmetic with angles

Your goal isn't to slice, concatenate or reverse lists. Your goal is to do basic arithmetic with degrees and keep the results between 0 and 359. For this, you really should use the modulo operator %:

>>> 90 % 360
90
>>> 390 % 360
30
>>> -60 % 360
300
>>> 360 % 360
0

Back to the question

If you only want to use this slicing for degrees with a constant increment, you could generate the desired list directly:

>>> STEP = 15
>>> list(range(0, 360, STEP))
[0, 15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165, 180, 195, 210, 225, 240, 255, 270, 285, 300, 315, 330, 345]
>>> def previous_degrees(start, n, step=STEP):
...     return [(start - i * step) % 360 for i in range(n + 1)]
... 
>>> previous_degrees(90, 12)
[90, 75, 60, 45, 30, 15, 0, 345, 330, 315, 300, 285, 270]
>>> previous_degrees(90, 12, 30)
[90, 60, 30, 0, 330, 300, 270, 240, 210, 180, 150, 120, 90]
>>> previous_degrees(90, 6, 45)
[90, 45, 0, 315, 270, 225, 180]

Your real question

You wrote in a comment:

This array of degrees is designed to work with a smooth rotation system that I'm trying to create in pygame. Normally I would just find the difference between the current direction and the target direction and increment from there, but since the rotation rolls over at zero I have to hardcode the values to make sure that it will always go the shortest route possible.

From two angles, you need to determine if you should turn clockwise or anticlockwise. You can use modulo again to make sure that the rotation will be between -180° and 179°:

def shortest_rotation(start_angle, end_angle):
    return (end_angle - start_angle + 180) % 360 - 180

Here's an example:

>>> shortest_rotation(0, 90)
90
>>> shortest_rotation(90, 0)
-90
>>> shortest_rotation(90, 90)
0
>>> shortest_rotation(90, 330)
-120
>>> shortest_rotation(0, 180)
-180
>>> shortest_rotation(0, 181)
-179
>>> shortest_rotation(0, 179)
179
>>> shortest_rotation(10, 350)
-20

You can now create a list of angles, turning in the shortest direction:

def rotation_steps(start_angle, end_angle, n):
    increment = shortest_rotation(start_angle, end_angle) / n
    return [(start_angle + i * increment) % 360 for i in range(n + 1)]

As an example:

>>> rotation_steps(90, 270, 12)
[90.0, 75.0, 60.0, 45.0, 30.0, 15.0, 0.0, 345.0, 330.0, 315.0, 300.0, 285.0, 270.0]
>>> rotation_steps(10, 350, 2)
[10.0, 0.0, 350.0]

The list uses float in order to avoid missing the end_angle if increment isn't an integer.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...