1
votes

I have a list I need to find an element and remove it.

The idea I'm going on is to remove it if it's the head and join that with removing it if it's the head of the tail. I have no idea how to do that though.

Any advice is appreciated.

This is what I've got

choice(8, X):-
  nl, write('\tRemove a student from roster:'),nl,nl,
  write('\tEnter student name or ID : '), read(S), remove(S, X, X2), nl, menu(X2).

remove(S, [], []):- write('\tStudent '), writef("%s", [S]), write(' is not in the roster.'),nl.

remove(S, [[I,N,G]|T], X):-
  S = I -> X = T2, remove(S, T, T2);
  T = [] -> X = [];
  X = [[I,N,G]|T2], remove(S, T, T2).

I want it to remove all occurrences.

3
Can you show some work here? You haven't even shown what you want the query to look like. And your definition isn't clear (do you want it to remove all occurrences or just the first one?).lurker
I just added what I've got on it so far.d0m1n1c
The reason I didn't add it to begin with, is that I only wanted the general idea of how to do it.d0m1n1c

3 Answers

2
votes

Stay pure by using tfilter/3 together with reified term inequality dif/3:

?- tfilter(dif(x),[x,1,2,x,3,4,5,x,6,x,x,7],Xs).
Xs = [1,2,3,4,5,6,7].                       % succeeds deterministically
0
votes
removes(S, [], []):- write('\tStudent '), writef("%s", [S]), write(' is not in the roster.'),nl.

removes(S, [[I,N,G]|T], X):- remove(S, [[I,N,G]|T], X).

remove(S, [], []).

remove(S, [[I,N,G]|T], X):-
  S = I -> X = T2, 
    write('\tStudent '),writef("%s", [S]),write(' removed.'),nl,
    remove(S, T, T2);
  S = N -> X = T2,
    write('\tStudent '),writef("%s", [S]),write(' removed.'),nl,
    remove(S, T, T2);
  X = [[I,N,G]|T2], remove(S, T, T2).

the link from lurker was helpful. I needed another function. Adding removes fixed it.

-1
votes

One way, using built-ins:

remove(X,L,R) :-      % to remove all X from L:
  append(P,[X|S],L),  % - break L into a prefix P, X itself and a suffix S
  append(P,S,T) ,     % - append the prefix and suffix together to form a new list
  remove(X,T,R)       % - and remove X from that list
  .                   %
remove(X,L,L) :-      % otherwise, succeed, leaving L unchanged
  \+ member(X,L)      % - if X is not contained in L
  .                   %

Or you can do it the hard way — not that hard! — and roll your own:

remove( X , []     , [] ) .      % removing X from the empty list yields the empty list
remove( X , [X|Ls] , R  ) :-     % removing X from a non-empty list consists of
  remove( X , Ls , R )           % - tossing X if it's the head of the list, and
  .                              % - recursing down.
remove( X , [L|Ls] , [L|R] ) :-  % or ...
  X \= L ,                       % - if X is not the head of the list,
  remove( X , Ls , R )           % - simply recursing down.
  .                              % Easy!

Not that this is no less clear or elegant than than using append/3 and, probably faster/more efficient.