Итак, я недавно начал использовать пролог, так как я начинаю использовать AI и FOL. Я заметил довольно много различий с другими языками, которые я использовал, такими как Python и Java, и мне трудно «сравнить» эти языки.

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

Входными данными является список кортежей, например: [(1,aa),(2,bb),(3,cc),(4,dd)].

Я пытаюсь написать функцию так, чтобы на выходе был СПИСОК ВТОРОГО ЭЛЕМЕНТА КАЖДОГО ТУПА в списке, а именно [aa, bb, cc, dd]

Я уже пробовал делать что-то вроде "extract_second_item([(1,aa),(2,bb),(3,cc),(4,dd)], [(_ , output)|_])". Но когда я запускаю эту функцию, она возвращает только второй элемент первого кортежа (aa), но, очевидно, не остальные.

Спасибо!

1
Roger Roger 17 Сен 2018 в 10:58

2 ответа

Лучший ответ

На самом деле кортеж - это составное:

?- write_canonical((a,b,c)).
','(a,','(b,c))
true.

Поэтому arg / 3 довольно функциональный для извлечения второго аргумента по позиции из кортежа:

?- arg(2,(a,b),X).
X = b.

Вы можете решить свою проблему компактно, используя лямбда выражение

?- maplist([X,Y]>>arg(2,X,Y), [(1,aa),(2,bb),(3,cc),(4,dd)], L).
L = [aa, bb, cc, dd].

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

?- maplist([X,Y]>>(X=(_,Y)), [(1,aa),(2,bb),(3,cc),(4,dd)], L).
L = [aa, bb, cc, dd].

Сопоставление с образцом может быть добавлено в лямбда-аргументы:

?- maplist([(_,Y),Y]>>true, [(1,aa),(2,bb),(3,cc),(4,dd)], L).
L = [aa, bb, cc, dd].

Вместо библиотеки (yall) вы можете выбрать библиотеку (лямбда), скорость торговли для переносимости:

?- use_module(library(lambda)).
true.

?- maplist(\X^Y^(X=(_,Y)), [(1,aa),(2,bb),(3,cc),(4,dd)], L).
L = [aa, bb, cc, dd].

В SWI-Prolog для этого требуется установить пакет (lambda),

?- pack_install(lambda).
2
CapelliC 17 Сен 2018 в 15:10

Вам нужно использовать простую рекурсию:

extract_second_item([], []).
extract_second_item([(_,X)|T], [X|T2]):- extract_second_item(T,T2).

Теперь запрос:

?- extract_second_item([(1,aa),(2,bb),(3,cc),(4,dd)], L).
L = [aa, bb, cc, dd].

@Lurker предлагает еще один отличный способ - использовать maplist/3:

Сначала мы определяем простой предикат, который возвращает второй элемент из кортежа:

second_item((_,X), X).

Затем мы сопоставляем second_item / 2 каждому кортежу в списке, используя maplist/3:

?-maplist(second_item, [(1,aa),(2,bb),(3,cc),(4,dd)], L).
L = [aa, bb, cc, dd].
3
coder 17 Сен 2018 в 14:42