问题
I want, given a list formed by A-B elements ([a-b,b-c,c-d]), check if some given element it's already in a list (which I will return), and if it's not, add any "A" or "B" element that is not in the output list yet.
I haven't really found any "easy" enough answer for me to understand yet (like, I found one with mappings and stuff I've never used nor seen).
So the output list would need to only have [a,b,c,d]
edit: what I'm trying to do is, I get called like this:
enumerate([a-b,b-c,c-d], EnumNodes, EnumArcs)
And I have to return two lists. First one gives the nodes (with this specific form:
[enum(1,a),enum(2,b),enum(3,c),enum(4,d)],
and second one gives the arcs (the conections) between said nodes.
So I am at the part where I "know" how to count and return items in a list, but I do not know the following:
-How to insert ONLY unique elements in a list
-How to first check if "A" is in the list, if not insert it, and then check if "B" is in the list, if not, insert it (reason for me not knowing this, I can't come with a way of invoking the rule, once it's done, twice, once for each element, each step of recursion, without making a mistake
回答1:
Are you looking for a clause like this?
% ensure(ELEMENT, LIST_IN, LIST_OUT)
% If X is already a member of L, then the result is L
ensure(X, L, L) :-
member(X, L), !.
% If not, the result is X appended to L
ensure(X, L, [X | L]).
Use:
1 ?- ensure(1, [1,2,3], O).
O = [1, 2, 3].
2 ?- ensure(2, [1,3], O).
O = [2, 1, 3].
I think this is the sort of thing you are looking for...
% enumerate(CONNECTIONS_IN, NODES_OUT, ARCS_OUT)
enumerate(C, N, A) :-
enum_nodes(C, [], N, 1),
create_arcs(C, N, A).
% enum_nodes(CONNECTIONS_IN, NODES_IN, NODES_OUT, START_ID)
% Fills up NODES_OUT with enums. New IDs start at START_ID...
enum_nodes([], N, N, _).
enum_nodes([A-B | T], N, NOUT, ID) :-
ensure_node(A, N, NTMP1, ID, ID1),
ensure_node(B, NTMP1, NTMP2, ID1, ID2),
enum_nodes(T, NTMP2, NOUT, ID2).
% ensure_node(NODE, NODES_IN, NODES_OUT, ID_IN, ID_OUT)
% Adds enum(ID_IN, NODE) to NODES_IN to produce NODES_OUT if NODE does not already exist in NODES_IN
ensure_node(NODE, NODES_IN, NODES_IN, ID, ID) :-
member(enum(_, NODE), NODES_IN), !.
ensure_node(NODE, NODES_IN, [enum(ID_IN, NODE) | NODES_IN], ID_IN, ID_OUT) :-
ID_OUT is ID_IN + 1.
% create_arcs(CONNECTIONS_IN, NODES_IN, ARCS_OUT).
% Create arcs - makes a list of arc(NODE_ID_1, NODE_ID_2)...
create_arcs([], _, []).
create_arcs([A-B | T], NODES, [arc(NODE_ID_A, NODE_ID_B) | TARCS]) :-
member(enum(NODE_ID_A, A), NODES),
member(enum(NODE_ID_B, B), NODES),
create_arcs(T, NODES, TARCS).
Example output:
1 ?- enumerate([a-b, c-d, d-a], N, A).
N = [enum(4, d), enum(3, c), enum(2, b), enum(1, a)],
A = [arc(1, 2), arc(3, 4), arc(4, 1)] .
If you do a trace, you can see it working...
2 ?- trace.
true.
[trace] 2 ?- enumerate([a-b, c-d, d-a], N, A).
Call: (6) enumerate([a-b, c-d, d-a], _G2634, _G2635) ? creep
Call: (7) enum_nodes([a-b, c-d, d-a], [], _G2634, 1) ? creep
Call: (8) ensure_node(a, [], _G2740, 1, _G2742) ? creep
Call: (9) lists:member(enum(_G2731, a), []) ? creep
Fail: (9) lists:member(enum(_G2731, a), []) ? creep
Redo: (8) ensure_node(a, [], _G2740, 1, _G2742) ? creep
Call: (9) _G2747 is 1+1 ? creep
Exit: (9) 2 is 1+1 ? creep
Exit: (8) ensure_node(a, [], [enum(1, a)], 1, 2) ? creep
Call: (8) ensure_node(b, [enum(1, a)], _G2749, 2, _G2751) ? creep
Call: (9) lists:member(enum(_G2740, b), [enum(1, a)]) ? creep
Fail: (9) lists:member(enum(_G2740, b), [enum(1, a)]) ? creep
Redo: (8) ensure_node(b, [enum(1, a)], _G2749, 2, _G2751) ? creep
Call: (9) _G2756 is 2+1 ? creep
Exit: (9) 3 is 2+1 ? creep
Exit: (8) ensure_node(b, [enum(1, a)], [enum(2, b), enum(1, a)], 2, 3) ? creep
Call: (8) enum_nodes([c-d, d-a], [enum(2, b), enum(1, a)], _G2634, 3) ? creep
Call: (9) ensure_node(c, [enum(2, b), enum(1, a)], _G2758, 3, _G2760) ? creep
Call: (10) lists:member(enum(_G2749, c), [enum(2, b), enum(1, a)]) ? creep
Fail: (10) lists:member(enum(_G2749, c), [enum(2, b), enum(1, a)]) ? creep
Redo: (9) ensure_node(c, [enum(2, b), enum(1, a)], _G2758, 3, _G2760) ? creep
Call: (10) _G2765 is 3+1 ? creep
Exit: (10) 4 is 3+1 ? creep
Exit: (9) ensure_node(c, [enum(2, b), enum(1, a)], [enum(3, c), enum(2, b), enum(1, a)], 3, 4) ? creep
Call: (9) ensure_node(d, [enum(3, c), enum(2, b), enum(1, a)], _G2767, 4, _G2769) ? creep
Call: (10) lists:member(enum(_G2758, d), [enum(3, c), enum(2, b), enum(1, a)]) ? creep
Fail: (10) lists:member(enum(_G2758, d), [enum(3, c), enum(2, b), enum(1, a)]) ? creep
Redo: (9) ensure_node(d, [enum(3, c), enum(2, b), enum(1, a)], _G2767, 4, _G2769) ? creep
Call: (10) _G2774 is 4+1 ? creep
Exit: (10) 5 is 4+1 ? creep
Exit: (9) ensure_node(d, [enum(3, c), enum(2, b), enum(1, a)], [enum(4, d), enum(3, c), enum(2, b), enum(1, a)], 4, 5) ? creep
Call: (9) enum_nodes([d-a], [enum(4, d), enum(3, c), enum(2, b), enum(1, a)], _G2634, 5) ? creep
Call: (10) ensure_node(d, [enum(4, d), enum(3, c), enum(2, b), enum(1, a)], _G2776, 5, _G2778) ? creep
Call: (11) lists:member(enum(_G2767, d), [enum(4, d), enum(3, c), enum(2, b), enum(1, a)]) ? creep
Exit: (11) lists:member(enum(4, d), [enum(4, d), enum(3, c), enum(2, b), enum(1, a)]) ? creep
Exit: (10) ensure_node(d, [enum(4, d), enum(3, c), enum(2, b), enum(1, a)], [enum(4, d), enum(3, c), enum(2, b), enum(1, a)], 5, 5) ? creep
Call: (10) ensure_node(a, [enum(4, d), enum(3, c), enum(2, b), enum(1, a)], _G2779, 5, _G2781) ? creep
Call: (11) lists:member(enum(_G2770, a), [enum(4, d), enum(3, c), enum(2, b), enum(1, a)]) ? creep
Exit: (11) lists:member(enum(1, a), [enum(4, d), enum(3, c), enum(2, b), enum(1, a)]) ? creep
Exit: (10) ensure_node(a, [enum(4, d), enum(3, c), enum(2, b), enum(1, a)], [enum(4, d), enum(3, c), enum(2, b), enum(1, a)], 5, 5) ? creep
Call: (10) enum_nodes([], [enum(4, d), enum(3, c), enum(2, b), enum(1, a)], _G2634, 5) ? creep
Exit: (10) enum_nodes([], [enum(4, d), enum(3, c), enum(2, b), enum(1, a)], [enum(4, d), enum(3, c), enum(2, b), enum(1, a)], 5) ? creep
Exit: (9) enum_nodes([d-a], [enum(4, d), enum(3, c), enum(2, b), enum(1, a)], [enum(4, d), enum(3, c), enum(2, b), enum(1, a)], 5) ? creep
Exit: (8) enum_nodes([c-d, d-a], [enum(2, b), enum(1, a)], [enum(4, d), enum(3, c), enum(2, b), enum(1, a)], 3) ? creep
Exit: (7) enum_nodes([a-b, c-d, d-a], [], [enum(4, d), enum(3, c), enum(2, b), enum(1, a)], 1) ? creep
Call: (7) create_arcs([a-b, c-d, d-a], [enum(4, d), enum(3, c), enum(2, b), enum(1, a)], _G2635) ? creep
Call: (8) lists:member(enum(_G2776, a), [enum(4, d), enum(3, c), enum(2, b), enum(1, a)]) ? creep
Exit: (8) lists:member(enum(1, a), [enum(4, d), enum(3, c), enum(2, b), enum(1, a)]) ? creep
Call: (8) lists:member(enum(_G2777, b), [enum(4, d), enum(3, c), enum(2, b), enum(1, a)]) ? creep
Exit: (8) lists:member(enum(2, b), [enum(4, d), enum(3, c), enum(2, b), enum(1, a)]) ? creep
Call: (8) create_arcs([c-d, d-a], [enum(4, d), enum(3, c), enum(2, b), enum(1, a)], _G2774) ? creep
Call: (9) lists:member(enum(_G2788, c), [enum(4, d), enum(3, c), enum(2, b), enum(1, a)]) ? creep
Exit: (9) lists:member(enum(3, c), [enum(4, d), enum(3, c), enum(2, b), enum(1, a)]) ? creep
Call: (9) lists:member(enum(_G2789, d), [enum(4, d), enum(3, c), enum(2, b), enum(1, a)]) ? creep
Exit: (9) lists:member(enum(4, d), [enum(4, d), enum(3, c), enum(2, b), enum(1, a)]) ? creep
Call: (9) create_arcs([d-a], [enum(4, d), enum(3, c), enum(2, b), enum(1, a)], _G2786) ? creep
Call: (10) lists:member(enum(_G2800, d), [enum(4, d), enum(3, c), enum(2, b), enum(1, a)]) ? creep
Exit: (10) lists:member(enum(4, d), [enum(4, d), enum(3, c), enum(2, b), enum(1, a)]) ? creep
Call: (10) lists:member(enum(_G2801, a), [enum(4, d), enum(3, c), enum(2, b), enum(1, a)]) ? creep
Exit: (10) lists:member(enum(1, a), [enum(4, d), enum(3, c), enum(2, b), enum(1, a)]) ? creep
Call: (10) create_arcs([], [enum(4, d), enum(3, c), enum(2, b), enum(1, a)], _G2798) ? creep
Exit: (10) create_arcs([], [enum(4, d), enum(3, c), enum(2, b), enum(1, a)], []) ? creep
Exit: (9) create_arcs([d-a], [enum(4, d), enum(3, c), enum(2, b), enum(1, a)], [arc(4, 1)]) ? creep
Exit: (8) create_arcs([c-d, d-a], [enum(4, d), enum(3, c), enum(2, b), enum(1, a)], [arc(3, 4), arc(4, 1)]) ? creep
Exit: (7) create_arcs([a-b, c-d, d-a], [enum(4, d), enum(3, c), enum(2, b), enum(1, a)], [arc(1, 2), arc(3, 4), arc(4, 1)]) ? creep
Exit: (6) enumerate([a-b, c-d, d-a], [enum(4, d), enum(3, c), enum(2, b), enum(1, a)], [arc(1, 2), arc(3, 4), arc(4, 1)]) ? creep
N = [enum(4, d), enum(3, c), enum(2, b), enum(1, a)],
A = [arc(1, 2), arc(3, 4), arc(4, 1)] .
来源:https://stackoverflow.com/questions/37326510/how-to-check-if-element-is-not-in-a-list-if-it-isnt-insert-it