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?

+3


source to share


1 answer


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.

      

+1


source







All Articles