How to check if element is not in a list, if it isn't, insert it

馋奶兔 提交于 2019-12-25 07:02:40

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!