I have开发者_StackOverflow a list like [apple, orange]
and I want to convert it to a string like "apple,orange"
in Prolog. Do you have any idea?
In SWI-Prolog you can simply use atomic_list_concat/3
and atom_string/2
:
?- atomic_list_concat([apple, banana, oranges], ',', Atom), atom_string(Atom, String).
Atom = 'apple,banana,oranges',
String = "apple,banana,oranges".
In SWI-Prolog you can use with_output_to/2
. Below are two versions, one using write/1
and the other writeq/1
. It's not clear from your question what kind of behaviour your require.
?- List = [apple, 'ora\\nge'], with_output_to(codes(Codes), write(List)),
format("~s", [Codes]).
[apple,ora\nge]
List = [apple, 'ora\\nge'],
Codes = [91, 97, 112, 112, 108, 101, 44, 111, 114|...].
?- List = [apple, 'ora\\nge'], with_output_to(codes(Codes), writeq(List)),
format("~s", [Codes]).
[apple,'ora\\nge']
List = [apple, 'ora\\nge'],
Codes = [91, 97, 112, 112, 108, 101, 44, 39, 111|...].
if you use swi-prolog you can also do the following:
1) use the string_to_list/2 (you can give a list and get a string or give a string and get a list). the problem is that it wont insert commas so you will have to insert commas between the elements of your list manually; something like
insert_commas([],[]).
insert_commas([H|T],[H,', '|TC]):-
insert_commas(T,TC).
so your predicate would be something like:
list_string_with_commas(L,S):-
insert_commas(L,LC),
string_to_list(S,LC).
2)you can use swritef/3 and string_concat/3. swritef/3 works like writef/2 but instead of writing in the output it creates a string with the data.
list_string_with_commas([],"").
list_string_with_commas([H,T],S):-
swritef(SH,"%t, ",[H]),
list_string_with_commas(T,ST),
string_concat(SH,ST,T).
you might want to do some tail recursion optimisations
I am a Prolog novice - but this is what I came up with.
list_codes([], "").
list_codes([Atom], Codes) :- atom_codes(Atom, Codes).
list_codes([Atom|ListTail], Codes) :-
atom_codes(Atom, AtomCodes),
append(AtomCodes, ",", AtomCodesWithComma),
append(AtomCodesWithComma, ListTailCodes, Codes),
list_codes(ListTail, ListTailCodes).
list_string(List, String) :-
ground(List),
list_codes(List, Codes),
atom_codes(String, Codes).
list_string(List, String) :-
ground(String),
atom_codes(String, Codes),
list_codes(List, Codes).
which gives:
?- list_string([], S).
S = '' .
?- list_string([apple], S).
S = apple .
?- list_string([apple, orange], S).
S = 'apple,orange' .
?- list_string([apple, orange, peach], S).
S = 'apple,orange,peach' .
and:
?- list_string(L, '').
L = [] .
?- list_string(L, 'banana').
L = [banana] .
?- list_string(L, 'banana,litchi').
L = ['banana,litchi'] .
term_string (30 char min S.O.)
Sorry, don't have enough rep to add this comment to Gavin Lock's answer. Gavin's solution is good so far as it goes, but it should be tweaked to avoid giving duplicate answers (or, rather, a variation on the same answer). The problem is that a list with a single atom will unify to two clauses in list_codes/2: the second AND the third clause. (A list with a single element still has a tail, i.e. the empty list.) I believe only the second clause binding is desired. The third clause seems to be designed to be recursive for lists that still have at least two elements. Therefore I recommend changing this clause to be:
list_codes([Atom,Next|ListTail], Codes) :-
atom_codes(Atom, AtomCodes),
list_codes([Next|ListTail], ListTailCodes),
append(AtomCodes, ",", AtomCodesWithComma),
append(AtomCodesWithComma, ListTailCodes, Codes).
This will only unify when the list has at least two elements, and will prevent getting two solutions.
精彩评论