Reputation: 33
I have a list of distances associated with each compass bearing from 1 to 360 degrees, also stored as a list. I would like to condense the list so as to give ranges of bearings over which the distance is associated, e.g.
From:
bearings = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
distance = [5, 10, 15, 15, 15, 20, 20, 10, 10, 5]
To:
bearings = [1, 2, 3-5, 6-7, 8-9, 10]
distance = [5, 10, 15, 20, 10, 5]
Any ideas what sort of approach to take this on with? Thanks in advance!
Upvotes: 2
Views: 93
Reputation: 7225
Just for fun, I tried doing this in one line with itertools.groupby
. If you're writing throwaway code for data munging or something, this will do. Otherwise, I recommend breaking it out into a for
loop so it's more maintainable.
from itertools import groupby
bearings = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
distance = [5, 10, 15, 15, 15, 20, 20, 10, 10, 5]
new_bearings, new_distance = zip(
*[
(f"{pairs[0][0]}-{pairs[-1][0]}", k)
if len(pairs) > 1
else (str(pairs[0][0]), pairs[0][1])
for k, pairs in [
(k, list(g))
for k, g in groupby(zip(bearings, distance), key=lambda x: x[1])
]
]
)
print(f"{new_bearings=}")
# new_bearings=('1', '2', '3-5', '6-7', '8-9', '10')
print(f"{new_distance=}")
# new_distance=(5, 10, 15, 20, 10, 5)
I hate it :-)
The idea is the inner loop is grouping by your distances and giving tuples where they're the same. You need to return (k, list(g))
because g
is an iterator and you need a list for len
and slicing.
Once you have the lists of tuples, the ugly string operations are to give your lower-upper
notation, or just converting the first element to a string if there's only a single pair.
Upvotes: 1
Reputation: 637
By 'clumping' the distance array by repeating values we can recreate the bearings array
There is probably a more python-ic way to do this, but this is somewhere to start!
bearings = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
distance = [5, 10, 15, 15, 15, 20, 20, 10, 10, 5]
clumps = []
current_clump = []
# Clump repeating distances together
last_val = None
for i in range(len(distance)):
current_val = distance[i]
# if this element (distance) is the same as the last, add it to the current clump
# otherwise add the current clump to our clumps list and create a new empty one
if current_val == last_val or last_val is None:
current_clump.append(current_val)
else:
clumps.append(current_clump)
current_clump = [current_val]
last_val = current_val
# Add the 'leftover' clump after the loop is done
clumps.append(current_clump)
# Create the output "ranged_indices" array that will have our desired ranged values
ranged_indices = []
current_indice = 0;
for i in range(len(clumps)):
current_len = len(clumps[i])
if current_len == 1:
ranged_indices.append(current_indice+1)
else:
high_end = (current_indice+current_len)
ranged_indices.append(str(current_indice+1)+'-'+str(high_end))
current_indice += current_len
print(ranged_indices)
print(clumps)
Upvotes: 1