Reputation: 113
I have a collection of lists each containing 16 items, and I want to find lists with 12 consecutive values either > or < than a specified threshold. For now, I have iterated through the lists and put 1 for values greater and -1 for values less than the threshold, and I used to following to eliminate those that don't have 12 of either.
if list.count(-1) >= 12 or list.count(1) >= 12:
How do I efficiently check for 12 consecutive values? (12 values can loop around) for example this would count
[1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1]
Currently I have 2 nested for loops, but I know this checks the same value multiple times.
for i in range(16):
light = 0
dark = 0
for j in range(12):
index = i + j
if index > 15:
index -= 15
if list[index] == 1:
light += 1
elif list[index] == -1:
dark += 1
else:
break
if dark > 0 and light > 0:
break
if dark == 12 or light == 12:
return True
Upvotes: 0
Views: 1614
Reputation: 40
You can loop through the list while keeping track how many times you've seen a specific value. Everytime you see a different value this counter resets (because you are looking for consecutive values).
def consective_values(input_list, target_value):
i = 0
count = 0
for _ in range(2 * len(input_list)):
if input_list[i] == target_value:
count += 1
else:
count = 0
if count == 12:
return True
i = (i + 1) % len(input_list)
return False
Because the consecutive values can loop around you have to be a bit more careful with the list indexing and the loop variable. The max number of loops is equal to twice the length of the list. When you still haven't found 12 consecutive values at this point you know there aren't any. TO have an index loop around a list you can always apply the modulo (%) operator
Upvotes: 0
Reputation: 64
If I've understood correctly what you want, then here are some ways to do it:
First off you can sort the list, putting every element in an order, and then doing a linear search and incrementing a counter every time it's the same value with the previous list element
a.sort()
count = 0
for i in range(16):
if count == 12:
break
if a[i - 1] == a[i]:
count += 1
Another way to do it is with the modulo operator, which doesn't require you sorting the list. And you can add some variables to check if you've done a full loop.
flag_count = 0
count = 0
i = 0
while True:
if count == 12 or flag_count == 2:
break
if a[i % 15] == a[(i + 1) % 15]:
count += 1
if i % 15 == 0:
flag_count += 1
i += 1
Upvotes: 0
Reputation: 36450
I would harness itertools.groupby
following way
import itertools
data = [1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1]
runs = [len(list(g)) for _,g in itertools.groupby(data)]
if data[0] == data[-1]:
runs[0] += runs.pop()
print(max(runs) >= 12) # True
Explanation: I use itertools.groupby
to get length of runs (in this case [7,4,5]
) - itertools.groupby
does group only adjacent equal elements, then if first and last values of data
are equal I extract last element from runs
and add it to first element (as you allow wraparound), then I check if longest run is equal or greater 12
.
Upvotes: 4