Problems with removing punctuation in a list of lists
I am trying to write a prologue that will remove all punctuation marks (.,!?, Etc.) from all lists in a list of lists. This is what I have so far:
delete_punctuation(_,[],_).
delete_punctuation(Character,[List|Tail],Resultlist) :-
delete(List,Character,NewList),
delete_punctuation(Character,Tail,[NewList|Resultlist]).
whereas for "Symbol" it will be 33! or 46 for. and so on, as I will only use this in character code lists. (I know the function will actually work for other items that I would like to remove from lists as well.)
The results I get when querying:
delete_punctuation(33,[[45,33,6],[4,55,33]],X).
just
|: true.
However, I want it to be:
|: X = [[45,6],[4,55]].
What do I need to improve?
source to share
For this problem, I would solve it by addressing two additional problems separately, namely:
- Filter / exclude character code from one list;
- Applying the solution to the above list of character code lists.
For this purpose, I would approach like this:
exclude2(_, [], []).
exclude2(Code, [Code|Xs], Ys) :-
!, % ignore the next clause if codes match
exclude2(Code, Xs, Ys).
exclude2(Code, [X|Xs], [X|Ys]) :-
% else, Code != X here
exclude2(Code, Xs, Ys).
Note that some implementations such as SWI-Prolog provide exclude/3
as built-in , so you may not need to define it yourself.
Now, to apply the above predicate to a list of lists:
delete_punctuation(_, [], []).
delete_punctuation(Code, [L|Ls], [NewL|NewLs]) :-
exclude(Code, L, NewL),
delete_punctuation(Code, Ls, NewLs).
However, again, depending on the implementation, the built-in can be used to achieve the same effect maplist/3
without having to define a new predicate:
?- maplist(exclude2(33), [[45,33,6],[4,55,33]], X). X = [[45, 6], [4, 55]] ; false.
nb if you want to use all of the built-in SWI functionality exclude/3
requires the test to be the target, e.g .:
?- maplist(exclude(==(33)), [[45,33,6],[4,55,33]], X). X = [[45, 6], [4, 55]] ; false.
For a more general approach, you can even add all the codes you want to exclude (for example, any and all punctuation marks) to the list to be used as a filter:
excludeAll(_, [], []).
excludeAll(Codes, [Code|Xs], Ys) :-
member(Code, Codes),
!,
excludeAll(Codes, Xs, Ys).
excludeAll(Codes, [X|Xs], [X|Ys]) :-
excludeAll(Codes, Xs, Ys).
Then you can add a list with all the codes to remove:
?- maplist(excludeAll([33,63]), [[45,33,6],[4,55,33,63]], X). X = [[45, 6], [4, 55]] ; false.
source to share