Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

count number of events in an array python

I have the following array:

a = [0,0,0,1,1,1,0,0,1,0,0,0,1,1,0,0,0,0,0,0,1,1,0,1,1,1,0,0,0]

Each time I have a '1' or a series of them(consecutive), this is one event. I need to get, in Python, how many events my array has. So in this case we will have 5 events (that is 5 times 1 or sequences of it appears). I need to count such events in order to to get:

b = [5]

Thanks

like image 712
hpnk85 Avatar asked Dec 05 '22 00:12

hpnk85


2 Answers

You could use itertools.groupby (it does exactly what you want - groups consecutive elements) and count all groups which starts with 1:

In [1]: from itertools import groupby

In [2]: a = [0,0,0,1,1,1,0,0,1,0,0,0,1,1,0,0,0,0,0,0,1,1,0,1,1,1,0,0,0]

In [3]: len([k for k, _ in groupby(a) if k == 1])
Out[3]: 5

what if I wanted to add a condition that an event is given as long as there are is 2 or more '0's in between.

This could be done using groupby and custom key function:

from itertools import groupby


class GrouperFn:
    def __init__(self):
        self.prev = None

    def __call__(self, n):
        assert n is not None, 'n must not be None'

        if self.prev is None:
            self.prev = n
            return n

        if self.prev == 1:
            self.prev = n
            return 1

        self.prev = n
        return n


def count_events(events):
    return len([k for k, _ in groupby(events, GrouperFn()) if k == 1])


def run_tests(tests):
    for e, a in tests:
        c = count_events(e)
        assert c == a, 'failed for {}, expected {}, given {}'.format(e, a, c)

    print('All tests passed')


def main():
    run_tests([
        ([0, 1, 1, 1, 0], 1),
        ([], 0),
        ([1], 1),
        ([0], 0),
        ([0, 0, 0], 0),
        ([1, 1, 0, 1, 1], 1),
        ([0, 1, 1, 0, 1, 1, 0], 1),
        ([1, 0, 1, 1, 0, 1, 1, 0, 0, 1], 2),
        ([1, 1, 0, 0, 1, 1], 2),
        ([0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0], 4)
    ])


if __name__ == "__main__":
    main()

The idea is pretty simple - when a 0 goes after a group of 1's, it could be a part of the group and therefore should be included in that group. The next event either continues the group (if the event is 1) or splits it (if the event is 0)

Note, that presented approach will work only when you need to count a number of events, since it splits [1, 1, 0, 0] as [[1, 1, 0], [0]].

like image 179
awesoon Avatar answered Dec 06 '22 12:12

awesoon


Math way (be careful with an empty array):

a = [0,0,0,1,1,1,0,0,1,0,0,0,1,1,0,0,0,0,0,0,1,1,0,1,1,1,0,0,0]
events = (a[0] + a[-1] + sum(a[i] != a[i-1] for i in range(1, len(a)))) / 2
print events

I like to think this is efficient :)

like image 26
lcastillov Avatar answered Dec 06 '22 12:12

lcastillov