2013-04-07 5 views
3

Мне нужно удалить только одно вхождение в список. На самом деле не имеет значения, первый или последний. Один матч нужно удалить.Удаление первого вхождения в список - пролог

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

deleteOne(_,[],[]). 

deleteOne(Term, [Term|Tail], Result) :- 
    deleteOne(Term, [], [Result|Tail]), !. 

deleteOne(Term, [Head|Tail], [Head|TailResult]) :- 
    deleteOne(Term, Tail, TailResult), !. 

Выход

41 ?- deleteOne(5,[2,3,1,5,2,3,1],X). 
X = [2, 3, 1, 5, 2, 3, 1]. 

Это работает, когда я заменить термин с пустой строкой или некоторой случайной строки.

deleteOne(Term, [Term|Tail], Result) :- 
    deleteOne("", Tail, Result), !. 

Выход

41 ?- deleteOne(5,[2,3,1,5,2,3,1],X). 
X = [2, 3, 1, 2, 3, 1]. 

Но я не думаю, что это лучшее решение по многим причинам. Не для моей текущей проблемы, но, например, для более длинных списков. Или, если список содержит пустую строку - не знаю, возможно ли это в Prolog.

Почему не первый пример работы? И какие существуют другие решения?

ответ

2

Ваш первый один не работает, потому что это не имеет особого смысла:

deleteOne(Term, [Term|Tail], Result) :- 
    deleteOne(Term, [], [Result|Tail]), !. 

Это означает, что результат следующего должен иметь текущий результат в его голове.

лучшим решением было бы это:

delete_one(_, [], []). 
delete_one(Term, [Term|Tail], Tail). 
delete_one(Term, [Head|Tail], [Head|Result]) :- 
    delete_one(Term, Tail, Result). 

Если вы хотите, чтобы это было решающим фактором, добавить сокращение на втором пункте. Как есть, он может это сделать:

?- delete_one(2, [1, 2, 3, 1, 2, 3], X). 
X = [1,3,1,2,3] ? ; 
X = [1,2,3,1,3] ? ; 
X = [1,2,3,1,2,3] ? ;  
no 
+0

Теперь я вижу, где я совершил свою ошибку. Рекурсия все же иногда меня смущает и глупо думает. Благодарим за то, что вы дали понять это и предложили лучшее решение. –

Смежные вопросы