2016-04-24 5 views
3

У меня есть список списков вроде этого:Пролог: удалить все пробелы в списке

[[q, ,w, ,e, ,r, ,t, ,z],[a, ,s, ,d, ,f, ,g, ,h],[y, ,x, ,c, ,v, ,b, ,n]] 

и мне нужно удалить все пробелы, за исключением последнего списка. Так что я хочу:

[[q,w,e,r,t,z],[a,s,d,f,g,h],[y, ,x, ,c, ,v, ,b, ,n]] 

Я пробовал:

deleteAll([_|[]],[]). 
deleteAll([Head|Tail],L) :- 
    deleteAll(Tail,_), 
    subtract(Head,[ ],L). 

Но он не работает. Я получаю onlny:

[q, ,w, ,e, ,r, ,t, ,z] 

Таким образом, кажется, что даже вычитать техника его подводит сопрягать [], как пространство. Как я могу это достичь?

+5

Как вы представляете пространства? Вам нужно написать '' ''! – false

ответ

3
 
:- set_prolog_flag(double_quotes, chars). 
:- use_module(library(double_quotes)). 

spdels([], []). 
spdels([Cs], [Cs]). 
spdels([Cs|Css], [Ds|Dss]) :- 
    Css = [_|_], 
    Dss = [_|_], 
    text_nospaces(Cs, Ds), 
    spdels(Css, Dss). 

text_nospaces([], []). 
text_nospaces([C|Cs], Ds0) :- 
    if_(C = ' ', Ds0 = Ds1, Ds0 = [C|Ds1]), 
    text_nospaces(Cs, Ds1). 


text_nospaces_bis(Cs, Ds) :- 
    tfilter(dif(' '), Cs, Ds). 

использованием и tfilter/3.

| ?- spdels(["a b c","d e","f g"], Cs). 
Cs = ["abc","de","f g"] ? ; 
no 
2

Поскольку @false уже указано [ ] это не пробел, а пустой список. Также ваш предикат описывает L как Head минус пустой список, и он не заботится о результате рекурсии (deleteAll(Tail,_)). Вот почему вы получаете неизменный первый список в качестве результата.

Подумайте о том, что предикат должен описать: отношение между двумя списками списков, где второй список содержит подсписки первого списка без пространства, за исключением самого последнего подсписка, что неизменна:

:- set_prolog_flag(double_quotes, chars). 

lists_withoutspace([X],[X]).     % last list unaltered 
lists_withoutspace([H1,H2|T1],[H1WoS|T2]) :- % H1Wos: 
    list_withoutspace(H1,H1WoS),     % first sublist without spaces 
    lists_withoutspace([H2|T1],T2).    % the same for the rests 

для list_withoutspace/2 можно использовать тэ встроенный предикат char_type/2, чтобы определить тип первого списка-элемента:

list_withoutspace([],[]).   % empty list contains no space 
list_withoutspace([X|T],L) :-  % X is not in the list 
    char_type(X,space),    % if it is space 
    list_withoutspace(T,L).   % relation must also hold for tail 
list_withoutspace([X|T],[X|L]) :- % X is in the list 
    char_type(X,alpha),    % if it is a letter 
    list_withoutspace(T,L).   % relation must also hold for tail 

Если вы хотите, чтобы соответствовать более чем буквы изменить alpha соответственно. Если вы запрашиваете этот предикат, вы получите желаемый результат:

?- lists_withoutspace([[q,' ',w,' ',e,' ',r,' ',t,' ',z],[a,' ',s,' ',d,' ',f,' ',g,' ',h],[y,' ',x,' ',c,' ',v,' ',b,' ',n]],L). 
L = [[q,w,e,r,t,z],[a,s,d,f,g,h],[y,' ',x,' ',c,' ',v,' ',b,' ',n]] ? ; 
no 

Или более компактно:

?- lists_withoutspace(["q w e r t z","a s d f g h","y x c v b n"],L). 
L = [[q,w,e,r,t,z],[a,s,d,f,g,h],[y,' ',x,' ',c,' ',v,' ',b,' ',n]] ? ; 
no 
+2

s (X).Бонусный вопрос: как я могу узнать/проверить автоматически (без прочтения всей документации), какие встроенные/предикаты библиотеки достаточно чисты для моего вкуса? – repeat

+2

@repeat: Я бы, наверное, попробовал две характеристики в теге-информации [tag: logic-purity]. В этом случае char_type/2 (я предполагаю, что это встроенный, на который вы ссылаетесь) успешно завершается, если создается один аргумент, но обобщение, самый общий запрос, приводит к ошибке создания. Однако способ, которым я его использую, второй аргумент всегда является «пространством», и его использование таким образом не нарушает коммутативности соединения, например. '? - X = '', char_type (X, space) .' и'? - char_type (X, пробел), X = '' .' дают тот же результат. В этом случае это достаточно хорошо для меня. – tas

+1

Thx 4 Ur ответить! Звучит неплохо для меня ... просто интересно, как это проверить автоматически, чтобы помочь программисту/кодеру/пользователю/себе увидеть границы между чистым и нечистым. – repeat

0

код:

deleteAllSpaces_except_last([X],[X]):-!.    % without last Element 

deleteAllSpaces_except_last([[]|Ys],[[]|Ys1]):-   % End of List inside List_of_lists 
     deleteAllSpaces_except_last(Ys,Ys1). 

deleteAllSpaces_except_last([[X|Xs]|Ys],Res):-   % if X=' ' then skip else add into New list inside list_of_lists 
     (X=' ',Res=[Xs1|Ys1];Res=[[X|Xs1]|Ys1]), 
     deleteAllSpaces_except_last([Xs|Ys],[Xs1|Ys1]). 

тест:

| ?- deleteAllSpaces_except_last([[q,' ',w,' ',e,' ',r,' ',t,' ',z],[a,' ',s,' ',d,' ',f,' ',g,' ',h],[y,' ',x,' ',c,' ',v,' ',b,' ',n]],L). 
L = [[q,w,e,r,t,z],[a,s,d,f,g,h],[y,' ',x,' ',c,' ',v,' ',b,' ',n]] ? ; 
no 

| ?- deleteAllSpaces_except_last([[q,' ',w,' ',e,' ',r,' ',t,' '],[],[y,' ',x,' ',c,' ',v,' ',b,' ',n]],L). 
L = [[q,w,e,r,t],[],[y,' ',x,' ',c,' ',v,' ',b,' ',n]] ? 
+1

'deleteAllSpaces_except_last ([[C], []], Xs) .' должен дать два ответа – false

+0

@false Я добавил' deleteAllSpaces_except_last ([[]], []). '? –

+1

'X = a, deleteAllSpaces_except_last ([[X], []], [[X], []]).' Правильно преуспевает, но то же самое без 'X = a' терпит неудачу. – false

3

Почему бы не делегировать "рекурсивная часть" в Прологе библиотеки предикатов?

основе tfilter/3 и dif/3 определяют spaces_gone/2 так:

 
:- use_module(library(lists), [same_length/2, reverse/2, maplist/3]). 

spaces_gone([], []). 
spaces_gone([A|As], [D|Ds]) :- 
    same_length(As, Ds), 
    reverse([A|As], [Last|Bs]), 
    maplist(tfilter(dif(' ')), Bs, Cs), 
    reverse([Last|Cs], [D|Ds]). 

Образец запроса с использованием SICStus Пролог 4.3.2:

| ?- set_prolog_flag(double_quotes, chars), 
    use_module(library(double_quotes)). 
% ... 
yes 

| ?- spaces_gone(["a b c","d e","f g"], Css). 
Css = ["abc","de","f g"] ? ; 
no 
Смежные вопросы