Keep nonzeros and their neighbours

JavaScript (ES6), 35 bytes

a=>a.filter((e,i)=>e|a[i-1]|a[i+1])

Works on floats too for two extra bytes.


Python, 50 bytes

f=lambda l,*p:l and l[:any(l[:2]+p)]+f(l[1:],l[0])

A recursive function that takes a tuple. Includes the first element if there's a nonzero value among either the first two elements or the previous value stored from last time. Then, removes the first element and recurses. The previous element is stored in the singleton-list p, which automatically packs to list and starts as empty (thanks to Dennis for 3 bytes with this).


55 bytes:

lambda l:[t[1]for t in zip([0]+l,l,l[1:]+[0])if any(t)]

Generates all length-3 chunks of the list, first putting zeroes on the start and end, and takes the middles elements of those that are not all zero.

An iterative approach turned out longer (58 bytes)

a=0;b,*l=input()
for x in l+[0]:a|b|x and print(b);a,b=b,x

This doesn't exactly work because b,*l needs Python 3, but Python 3 input gives a string. The initialization is also ugly. Maybe a similar recursive approach would work.

Unfortunately, the indexing method of

lambda l:[x for i,x in enumerate(l)if any(l[i-1:i+2])]

doesn't work because l[-1:2] interprets -1 as the end of the list, not a point before its start.


Haskell, 55 48 bytes

h x=[b|a:b:c:_<-scanr(:)[0]$0:x,any(/=0)[a,b,c]]

Usage example: h [0,0,0,8,0,1,0,0] -> [0,8,0,1,0].

scanr rebuilds the input list x with an additional 0 at the start and end. In each step we pattern match 3 elements and keep the middle one if there's at least one non-zero element.

Thanks @xnor for 7 bytes by switching from zip3 to scanr.