Merging Lists and Writing Delimited Records

View: New views
3 Messages — Rating Filter:   Alert me  

Merging Lists and Writing Delimited Records

by Carroll, Michael L. :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Some parts of this message have been removed. Learn more about Nabble's security policy.

All,

 

In case any of you might find these useful (I have), here are a couple of predicates that help merge lists of lists and produce delimited records (to be read by something like Excel).  They seem to work fine for my work, but there may be corner cases where things fall apart.  At any rate, have at it.

 

% The following little predicate will facilitate the merging of arbitrary number of lists:

 

% heads/3:  Given a list of lists LoL, produce a list consisting only of the heads of the lists in LoL.

%           As a by product, heads/3 also produces the list LoT of the remaining tails of lists in LoL. 

%             It returns LoH=[] and LoT=[], when LoL is empty.

 

heads(LoL,LoH,LoT) :- heads(LoL,[],LoH,[],LoT).

 

heads([],LoH,LoH,LoT,LoT) :- !.

heads([[H|Tail]|T],HAcc1,LoH,TAcc1,LoT) :-

                        append(HAcc1,[H],HAcc2),

                        append(TAcc1,[Tail],TAcc2),

                        heads(T,HAcc2,LoH,TAcc2,LoT).

 

%  writeDelimRecs/3:  Assume lists of atoms and write delimited records to a given stream.

%  Writes nothing if LoL contains an empty list.

 

writeDelimRecs(_,_,LoL) :- member([],LoL),!.

writeDelimRecs(Stream,Delim, LoL) :- heads(LoL,LoH,LoT),

                                                            concat_atom(LoH,Delim,Rec),

                                                            write(Stream,Rec), nl(Stream),

                                                            writeDelimRecs(Stream,Delim,LoT).

 

Regards,
Mike

Michael L. Carroll
Software Integrator
GPS SE&I Program
SAIC
310-416-8357
BB: 424-207-7221

 


Re: Merging Lists and Writing Delimited Records

by Richard O'Keefe :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


On Oct 30, 2009, at 2:42 PM, Carroll, Michael L. wrote:

> All,
>
> In case any of you might find these useful (I have), here are a  
> couple of predicates that help merge lists of lists and produce  
> delimited records (to be read by something like Excel).  They seem  
> to work fine for my work, but there may be corner cases where things  
> fall apart.  At any rate, have at it.
>
> % The following little predicate will facilitate the merging of  
> arbitrary number of lists:
>
> % heads/3:  Given a list of lists LoL, produce a list consisting  
> only of the heads of the lists in LoL.
> %           As a by product, heads/3 also produces the list LoT of  
> the remaining tails of lists in LoL.
> %             It returns LoH=[] and LoT=[], when LoL is empty.
>
> heads(LoL,LoH,LoT) :- heads(LoL,[],LoH,[],LoT).
>
> heads([],LoH,LoH,LoT,LoT) :- !.
> heads([[H|Tail]|T],HAcc1,LoH,TAcc1,LoT) :-
>                         append(HAcc1,[H],HAcc2),
>                         append(TAcc1,[Tail],TAcc2),
>                         heads(T,HAcc2,LoH,TAcc2,LoT).

Aside from the rather confusing name and the very strange indentation,
this is essentially the ml_taketop/3 predicate from the DEC-10 Prolog
library MULTIL.PL, which has been freely available on the web since
the early 1980s.

%.  ml_taketop(?Lists, ?Heads, ?Tails)
%   is true when Lists is a list of non-empty lists, Heads is a list
%   whose elements are the heads of the elements of Lists, and Tails
%   is a list whose elements are the tails of Lists.

ml_taketop([], [], []).
ml_taketop([[Head|Tail]|Lists], [Head|Heads], [Tail|Tails]) :-
         ml_taketop(Lists, Heads, Tails).

This was a private predicate of the module (note the "." after the
first "%", it told the documentation extractor not to extract this
comment).  The "ml_" prefix is because it comes from DEC-10 Prolog,
which didn't have modules.  As it wasn't exported, the fact that
this name isn't that helpful either didn't matter much.

>
> %  writeDelimRecs/3:  Assume lists of atoms and write delimited  
> records to a given stream.
> %  Writes nothing if LoL contains an empty list.

ThisIsNotJavaSoYouDoNotHaveToWriteNamesThatNoOneCanReadWithoutPain.

>
> writeDelimRecs(_,_,LoL) :- member([],LoL),!.
> writeDelimRecs(Stream,Delim, LoL) :- heads(LoL,LoH,LoT),
>                                                              
> concat_atom(LoH,Delim,Rec),
>                                                              
> write(Stream,Rec), nl(Stream),
>                                                              
> writeDelimRecs(Stream,Delim,LoT).

What you have here is not so much a "list of lists",
but a TABLE presented as a list of columns, rather than the
somewhat easier-to-handle list of rows.

The I/O predicates with a Stream argument should never have been
invented.  Every time you call a built-in predicate with such an
argument, it has to check it again and again and again and again.
Switch to the new stream, do all the writing you want, switch
back, and there are just two checks.  with_output_to/2 is an
extremely useful command.  So use it.

write_delimited_records(Stream, Columns, Delimiter) :-
     with_output_to(Stream, write_delimited_records(Columns,  
Delimiter)).

write_delimited_records(Columns, Delimiter) :-
     ml_taketop(Columns, Top_Row, Columns1),
     write_delimited_record(Top_Row, Delimiter),
     write_delimited_records(Columns1, Delimiter).
write_delimited_records(_, _).

There's a general rule of thumb I call "garbage avoidance", except
when I'm talking to people who've listened to Fred Dagg, when I
call it the Bruce Bayliss Principle.  (From a comedy skit:  what
should you do about all the garbage wrapping material?  Bruce's
idea: don't produce it in the first place.)  SWI Prolog _can_
garbage collect the atom table, but why concatenation stuff in
the first place if the only thing you are going to do with it
is print it?

write_delimited_record([Last], _) :- !,
     write(Last), nl.
write_delimited_record([Item|Items], Delimiter) :-
     write(Item), write(Delimiter),
     write_delimited_record(Items, Delimiter).

Of course, this misses one of the most important things in writing
CSV-like files, and that is to insert any necessary quoting, but
that's left as an exercise for the reader.


>
_______________________________________________
SWI-Prolog mailing list
SWI-Prolog@...
https://mailbox.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog

RE: Merging Lists and Writing Delimited Records

by Stiffler :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Some parts of this message have been removed. Learn more about Nabble's security policy.
Thanks for sharing.

Parker


From: MICHAEL.L.CARROLL@...
To: swi-prolog@...
Subject: [SWIPL] Merging Lists and Writing Delimited Records
Date: Thu, 29 Oct 2009 18:42:33 -0700

All,

 

In case any of you might find these useful (I have), here are a couple of predicates that help merge lists of lists and produce delimited records (to be read by something like Excel).  They seem to work fine for my work, but there may be corner cases where things fall apart.  At any rate, have at it.

 

% The following little predicate will facilitate the merging of arbitrary number of lists:


[...]



New Windows 7: Find the right PC for you. Learn more.