1

I have a query which is a list of numbers. I want to get the ranges of indices in which the number 1 appears. The range starts when 1 appears and ends on the index in which it doesn't appear. I have made an example to illustrate this.

query= [0,0,0,0,0,1,1,1,0,1,0,0,1,1,0]

answer = [[5,8],[9,10],[12,14]]

Note: I am not looking for the first and last index of some value in a list in Python. I'm looking for all the places in which they start and end.

Update: From some of the suggested answers below it looks like Itertools is quite handy for this stuff.

piccolo
  • 2,093
  • 3
  • 24
  • 56
  • Have a look at: https://stackoverflow.com/questions/522372/finding-first-and-last-index-of-some-value-in-a-list-in-python – caiomcg Jul 31 '19 at 12:50
  • 1
    Possible duplicate of [Finding first and last index of some value in a list in Python](https://stackoverflow.com/questions/522372/finding-first-and-last-index-of-some-value-in-a-list-in-python) – bharatk Jul 31 '19 at 12:51
  • 1
    @caiomcg I don't think this is the same thing as I'm not looking for the first and last occurrence of 1, I'm looking for all the regions where they are joined together. – piccolo Jul 31 '19 at 12:54
  • @bharatk see above – piccolo Jul 31 '19 at 12:54
  • 1
    What have you tried so far ? – IMCoins Jul 31 '19 at 12:55
  • You can implement the algorithm by looking at the first occurence and iterating from that position until the number is no longer what you were searching for and doing it recursively for new occurences – caiomcg Jul 31 '19 at 12:55

6 Answers6

2

You could also use itertools.groupby for this. Use enumerate to get the indices, then groupby the actual value, then filter by the value, finally get the first and last index from the group.

>>> from itertools import groupby
>>> query = [0,0,0,0,0,1,1,1,0,1,0,0,1,1,0]
>>> [(g[0][0], g[-1][0]+1) for g in (list(g) for k, g in
...   groupby(enumerate(query), key=lambda t: t[1]) if k == 1)]
...
[(5, 8), (9, 10), (12, 14)]
tobias_k
  • 81,265
  • 12
  • 120
  • 179
2

You can use itertools.dropwhile to do this.

>>> query = [0,0,0,0,0,1,1,1,0,1,0,0,1,1,0]
>>> n = 1
>>>
>>> from itertools import dropwhile
>>> itr = enumerate(query)
>>> [[i, next(dropwhile(lambda t: t[1]==n, itr), [len(query)])[0]] for i,x in itr if x==n]
[[5, 8], [9, 10], [12, 14]]
Sunitha
  • 11,777
  • 2
  • 20
  • 23
1
query= [0,0,0,0,0,1,1,1,0,1,0,0,1,1,0]
first = 0 # Track the first index in the current group
ingroup = False # Track whether we are currently in a group of ones
answer = []
for i, e in enumerate(query):
    if e:
        if not ingroup:
            first = i
    else:
        if ingroup:
            answer.append([first, i])
    ingroup = e
if ingroup:
    answer.append([first, len(query)])
>>> answer
[[5, 8], [9, 10], [12, 14]]

I think you probably want something like this.

StardustGogeta
  • 3,331
  • 2
  • 18
  • 32
1

you can just use basic for loop and if statement where are you checking where the series of '0' changes to a series of '1' and vice versa

query= [0,0,0,0,0,1,1,1,0,1,0,0,1,1,0]

r_0 = []
r_1 = []

for i in range(len(query)-1):
    if query[i] == 0 and query[i+1] == 1:
        r_0.append(i+1) # [5, 9, 12]
    if query[i] == 1 and query[i + 1] == 0:
        r_1.append(i + 1) # [8, 10, 14]

print (list(zip(r_0,r_1)))

output:

[(5, 8), (9, 10), (12, 14)]
ncica
  • 7,015
  • 1
  • 15
  • 37
1

Hope this helps. Its a solution without foor-loops

from itertools import chain

query = [0,0,0,0,0,1,1,1,0,1,0,0,1,1,0]

result = list(zip(
    filter(lambda i: query[i] == 1 and (i == 0 or query[i-1] != 1), range(len(query))),
    chain(filter(lambda i: query[i] != 1 and query[i-1] == 1, range(1, len(query))), [len(query)-1])
))
print(result)

The output is:

[(2, 3), (5, 8), (9, 10), (12, 14)]
Victor Ruiz
  • 1,192
  • 9
  • 9
0

Wanted to share a recursive approach

query= [0,0,0,0,0,1,1,1,0,1,0,0,1,1,0]

def findOccurrences(of, at, index=0, occurrences=None):
    if occurrences == None: occurrences = [] # python has a weird behavior over lists as the default
                                           # parameter, unfortunately this neets to be done

    try:
        last = start = query.index(of, index)

        for i in at[start:]:
            if i == of:
                last += 1
            else:
                break

        occurrences.append([start, last])
        return findOccurrences(of, at, last, occurrences)
    except:
        pass
    return occurrences


print(findOccurrences(1, query))
print(findOccurrences(1, query, 0)) # Offseting
print(findOccurrences(0, query, 9)) # Offseting with defaul list
caiomcg
  • 501
  • 10
  • 23