# Trim elements from the ends of a list

The aim is to trim elements in from the ends of a list, depending on if they are in a second list of "falsey" results.

For example, if the first list is [-1, 1, 2, 0, -1, 3, -1, 4, -1, -1] and the second is [-1], then we would remove all leading and trailing -1s from the first input, but not any -1s in the middle: [1, 2, 0, -1, 3, -1, 4]

You may take input in any allowed method and this is so the shortest code in bytes wins.

• Let us continue this discussion in chat to prevent extended discussion in comments. Mar 30 at 17:32
• Additionally, I would suggest adding in some more test cases, including ones where the "falsey" list has more than one element Mar 30 at 18:28
• From being closed, to being reopened, and finally to making it to the HNQ, this post has seen it all... Apr 2 at 1:27

f v|g<-reverse.snd.span(elemv)=g.g


Try it online!

• -1 byte thanks to xnor.

## How?

f v                     -- define a function f that takes as input a list v of falsey values
|g<-                  --   inside the definition, define a new function g that...
reverse             --     reverses...
.snd                --     the second element of...
.span               --     a tuple (say (x,y)) where x is the longest prefix of elements that...
(elemv)         --       belong to v...
--     and y is the rest of the list
=g.g                  --   f is defined as the composition g.g (basically apply g twice)

• I think you can use snd.span for dropWhile
– xnor
Mar 30 at 18:41

# Pyth, 3 bytes

.sF


Try it here!

• I'm not sure how Pyth handles 2 inputs, but is it possible to remove the F and take the two inputs separately? Mar 30 at 21:30
• Pyth takes input from the lines of stdin. Unfortunately, only the first input (i.e. the first line) can be implicit. You could take the inputs separately, but it wouldn't save any bytes. Mar 30 at 22:00

# Factor + math.unicode, 19 bytes

[ '[ _ ∈ ] trim ]


Try it online!

## Explanation:

It's a quotation (anonymous function) that takes two sequences as input and returns one sequence as output.

• '[ _ ∈ ] Push a fried quotation to the data stack to be used later by trim. Whatever is on top of the data stack gets slotted into the quotation at the _. This will be the list of elements to trim.
• trim Take a sequence and a quotation and apply the quotation to elements on both ends of the sequence, removing elements for which the quotation returns t. Stop when f is encountered.
• ∈ Take an object and a sequence and return t if the object is in the sequence. Shorthand for member?.
• Nice, exactly what I thought of when I saw the challenge. Mar 30 at 23:09

# Java, 89 bytes

a->b->a.dropWhile(b::contains).sorted((c,d)->-1).dropWhile(b::contains).sorted((c,d)->-1)


Try it online!

# Java, 125 bytes

a->b->{int i=-1,j=a.length;for(;b.contains(a[++i]););for(;b.contains(a[--j]););return java.util.Arrays.copyOfRange(a,i,j+1);}


Try it online!

• 86 bytes, using LinkedList Apr 1 at 10:44
• @OlivierGrégoire Nice idea. You could post that as another answer. Apr 1 at 13:04
• Okay, I've done it. Apr 1 at 14:38

# JavaScript (V8), 78 62 bytes

-16 bytes thanks to @Original Original Original VI

(a,s,g=x=>s.includes(x[0])?g(x.slice(1)):x.reverse())=>g(g(a))


Old:

a=>n=>(t=z=>z.findIndex(d=>!n.includes(d)),a.slice(t(a),-t([...a].reverse())))


Can probably be shortened by a ton

• f([-1, 1, 2, 0, -1, 3, -1, 4, -1, -1])([2, -1, 1]) seems to give an empty array, am I doing something wrong or is there a bug in the code? Mar 30 at 18:33
• @CommandMaster Not sure, I just golfed it and that seemed to fix it Mar 30 at 18:35
• You can get to 62 bytes by shifting stuff around a bit and not using findIndex.
– user
Mar 30 at 18:38

# Scala, 46 bytes

s=>1.to(2)./:(_)((a,_)=>a.reverse dropWhile s)


Try it in Scastie!

s =>                            //The Set of falsy items
1.to(2)                       //Make a range [1, 2] to trim twice
./:                         //Fold over it,
(_)                         //starting with the list to trim
((a, _) =>                  //The list a and the number, which is ignored
a.reverse                  //Reverse the list
dropWhile                 //And drop while
s)                        //Each item is present in s


## Same length, but more boring

s=>_.dropWhile(s).reverse.dropWhile(s).reverse


Try it in Scastie!

Boring.

# Python 3, 68 bytes

f=lambda a,b:a[-1]in b and f(a[:-1],b)or a[0]in b and f(a[1:],b)or a


Try it online!

• You can save 3 bytes by using python 2: Try it online! Mar 30 at 22:24
• @qwatry That's a significantly different answer; you should post it as your own.
– Neil
Mar 31 at 9:04
• Ok. Yeah, I was wondering if I should. Mar 31 at 10:27

# J, 21 bytes

[#~[:(>./\*>./\.)1-e.


Try it online!

# R, 57 55 bytes

function(x,y,+=cumprod)x[!+x%in%y&!rev(+rev(x)%in%y)]


Try it online!

Finds matching elements (x %in% y) as vector of TRUE/FALSE values, and calculates the cumulative product (cumprod, re-assigned to + here to save bytes) to convert everything after the first FALSE to zero. Then does the same from the other end (by reversing x and the cumprod). Finally, negates (!) to select only the non-terminal-matching elements of x.

• I had some hopelessly complicated scheme with outer(x,y,'=='), didn't even think about %in%! Mar 31 at 14:19

# APL (Dyalog Extended), 4 bytes (SBCS)

Anonymous infix function.

⌂deb


Try it online!

A library function: delete ending blanks using the left argument as a list of what is considered "blanks".

# Python 2, 64 bytes

a,f=input()
for i in-1,0:
while a and a[i]in f:a.pop(i)
print a


The a and is necessary if the falsey list, f, contains all the elements of a and the completely stripped list will be empty. Without it, the program errors with IndexError: list index out of range.

Try it online!

# Husk, 7 5 bytes

Edit: -2 bytes thanks to Leo

‼(↔↓€


Try it online!

How?

↔↓€ removes the falsy elements from one end of the list, and then flips it:

 ↓    # drop the longest prefix of arg2 with elements that satisfy:
€   # are present in arg1
↔     # then reverse the result


So we just need to do this twice (to remove from both ends of the list, and to restore the list to its original orientation):
( groups ↔↓€ together (the parentheses are automatically closed at the end of the program), and the higher-order function ‼ runs a function provided as an argument twice.

• Wanna do something twice? There's a builtin for that‼ Try it online!
– Leo
Mar 31 at 5:15

# Jelly, 1 byte

t


Try it online!

A builtin that does exactly this. Works with multiple "falsey" values as well: Try it online!

# 05AB1E, 1 byte

Ú


Try it online!

A builtin which trims.

• Hey, I was about to post this… >:( Mar 30 at 19:34

# JavaScript (ES6), 56 bytes

Expects (a)(b), where a is the array to trim, using the values in the set b.

a=>b=>(g=a=>a.reverse().filter(i=c=>i|=!b.has(c)))(g(a))


Try it online!

# Desmos, 227 215 bytes

z(A)=length(A)
h(l,a,k)=\left\{l[a]=k:0,1\right\}
f(a,b)=\sum_{n=1}^{z(b)}(1-h(b,n,a))
s=f(A,B)
j(A,B)=A[\sum_{N=1}^{z(s)}N(1-h(s,N,0))\prod_{a=1}^{N-1}h(s,a,0)...z(A)]
p=j(A,B)
q=j(p[z(p)...1],B)
m(A,B)=q[z(q)...1]


Try It On Desmos!

Try It On Desmos!(Prettified Version)

Final function is $$\m(a,b)\$$, where $$\a\$$ is the list that is being trimmed, and $$\b\$$ is the list of "falsey" values that are trimmed from $$\a\$$.

Much harder than I initially anticipated because Desmos has limited list functionality. Hopefully it's fine if I output an one-element list with the one element being undefined([undefined]) when the output is supposed to be an empty list([]). If it isn't fine then tell me and I can fix(but it would cost more bytes ☹️)

Note: Not too sure why, but you can't directly paste the code into Desmos for some reason. You have to paste each expression one at a time in order for it to work.

# Wolfram Language (Mathematica), 33 bytes

#//.{e=#|##&@@#2,a___,e...}:>{a}&


Try it online!

-6 bytes and correction from @att

• How do you take a list to trim on? It seems like it can only take a single falsey value, though maybe I'm missing something Mar 30 at 18:28
• @CommandMaster fixed.. Mar 30 at 18:42
• 33 bytes (Fold is also insufficient if the ends of the list aren't ordered the same way as in the falsy list)
– att
Mar 30 at 22:36

# Red, 70 bytes

func[b t][while[find t b/1][take b]while[find t last b][take/last b]b]


Try it online!

# Using parse, 123 bytes

func[b t][r: copy[]foreach n t[append r reduce['quote n '|]]take/last r
parse b[remove some r to[any r end]remove some r]b]


Try it online!

# Retina 0.8.2, 52 bytes

m^|$, (^)?,(([^,]+,)(?=.*¶.*,\3))*(¶.*)?(?(1)|$)



Try it online! Explanation:

m^|$,  Wrap both lists in additional commas. (^)?,  Record whether this match is at the very start, but at the very least start at a comma. (([^,]+,)(?=.*¶.*,\3))*  Match any number of terms which exist in the second array. (¶.*)?  Optionally match the second array. (?(1)|$)


If the match did not begin at the start, then it must end at the end.




Delete the matching values.

# Java (JDK), 86 bytes

l->b->{while(b.contains(l.peek()))l.pop();while(b.contains(l.getLast()))l.pollLast();}


Try it online!

Uses a LinkedList as input/output.

• You could also make it accept the more general Deque interface. Apr 1 at 14:39
• @iota Yes that was my first idea, but since the challenge speaks of list, I tried to stay in the spirit of it. Apr 2 at 9:49

# Excel, 70 bytes

=LET(x,A1#,r,ROW(x),y,IF(x>-1,r,""),FILTER(x,(r>=MIN(y))*(r<=MAX(y))))