How to check if element is not in a list, if it is

2019-09-10 03:46发布

问题:

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)] .


标签: prolog