Search code examples
prologdcg

Using DCG remove non-numbers from a list


I need to write a predicate CleanList/3 in Prolog by using which parses a list and returns a new list with the same numbers but all elements that are not a number removed.

For an example:

?- cleanList([1,2,d,67,3.2,'CSI2120',foo,5],LL).
LL = [1, 2, 67, 3.2, 5].

I wrote the base case and struggling to implement DCG with the recursive case. Can someone help me with this?

Base Case:

cleanList(L,LL) :- cleanList(LL,L,[]),!.

Solution

  • You could start by defining the base case like:

    cleanlist([]) --> [].
    

    which is pretty simple, all it does is returning empty list when the argument to cleanlist/1 is empty list. You can also define the clause:

    cleanlist([H|T]) --> (  {number(H)}  -> [H],  cleanlist(T) ;  cleanlist(T) ).
    

    which keeps the head of the lists H iff it is a number and call recursively cleanlist/1.

    Examples:

    ?- phrase( cleanlist([1]) ,L ).
    L = [1].
    
    ?- phrase( cleanlist([1,3]) ,L ).
    L = [1, 3].
    
    ?- phrase( cleanlist([1,2,a,c,3]) ,L ).
    L = [1, 2, 3].
    
    ?- phrase( cleanlist([1,2,a,c,3,m,k,l,o,"ABC",12]) ,L ).
    L = [1, 2, 3, 12].
    
    ?- phrase( cleanlist([a,b]) ,L ).
    L = [].
    
    ?- phrase( cleanlist([A,1,b]) ,L ).
    L = [1].