163 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Prolog
		
	
	
	
	
	
			
		
		
	
	
			163 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Prolog
		
	
	
	
	
	
/*  $Id: pairs.pl,v 1.1 2008-02-12 17:03:52 vsc Exp $
 | 
						|
 | 
						|
    Part of SWI-Prolog
 | 
						|
 | 
						|
    Author:        Jan Wielemaker
 | 
						|
    E-mail:        wielemak@science.uva.nl
 | 
						|
    WWW:           http://www.swi-prolog.org
 | 
						|
    Copyright (C): 1985-2006, University of Amsterdam
 | 
						|
 | 
						|
    This program is free software; you can redistribute it and/or
 | 
						|
    modify it under the terms of the GNU General Public License
 | 
						|
    as published by the Free Software Foundation; either version 2
 | 
						|
    of the License, or (at your option) any later version.
 | 
						|
 | 
						|
    This program is distributed in the hope that it will be useful,
 | 
						|
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
    GNU General Public License for more details.
 | 
						|
 | 
						|
    You should have received a copy of the GNU General Public
 | 
						|
    License along with this library; if not, write to the Free Software
 | 
						|
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
						|
 | 
						|
    As a special exception, if you link this library with other files,
 | 
						|
    compiled with a Free Software compiler, to produce an executable, this
 | 
						|
    library does not by itself cause the resulting executable to be covered
 | 
						|
    by the GNU General Public License. This exception does not however
 | 
						|
    invalidate any other reasons why the executable file might be covered by
 | 
						|
    the GNU General Public License.
 | 
						|
*/
 | 
						|
 | 
						|
:- module(pairs,
 | 
						|
	  [ pairs_keys_values/3,
 | 
						|
	    pairs_values/2,
 | 
						|
	    pairs_keys/2,
 | 
						|
	    group_pairs_by_key/2,
 | 
						|
	    transpose_pairs/2,
 | 
						|
	    map_list_to_pairs/3
 | 
						|
	  ]).
 | 
						|
 | 
						|
/** <module> Operations on key-value lists
 | 
						|
@ingroup swi
 | 
						|
 | 
						|
This module implements common operations on  Key-Value lists, also known
 | 
						|
as  _Pairs_.  Pairs  have  great  practical  value,  especially  due  to
 | 
						|
keysort/2 and the library assoc.pl.
 | 
						|
 | 
						|
This library is based  on  disussion   in  the  SWI-Prolog  mailinglist,
 | 
						|
including specifications from Quintus and a  library proposal by Richard
 | 
						|
O'Keefe.
 | 
						|
 | 
						|
@see	keysort/2, library(assoc)
 | 
						|
@author Jan Wielemaker
 | 
						|
*/
 | 
						|
 | 
						|
%%	pairs_keys_values(?Pairs, ?Keys, ?Values) is det.
 | 
						|
%
 | 
						|
%	True if Keys holds the keys of Pairs and Values the values.
 | 
						|
%	
 | 
						|
%	Deterministic if any argument is instantiated to a finite list
 | 
						|
%	and the others are either free or finite lists.
 | 
						|
 | 
						|
pairs_keys_values(Pairs, Keys, Values) :-
 | 
						|
	(   nonvar(Pairs) ->
 | 
						|
	    pairs_keys_values_(Pairs, Keys, Values)
 | 
						|
	;   nonvar(Keys) ->
 | 
						|
	    keys_values_pairs(Keys, Values, Pairs)
 | 
						|
	;   values_keys_pairs(Values, Keys, Pairs)
 | 
						|
	).
 | 
						|
 | 
						|
pairs_keys_values_([], [], []).
 | 
						|
pairs_keys_values_([K-V|Pairs], [K|Keys], [V|Values]) :-
 | 
						|
	pairs_keys_values_(Pairs, Keys, Values).
 | 
						|
 | 
						|
keys_values_pairs([], [], []).
 | 
						|
keys_values_pairs([K|Ks], [V|Vs], [K-V|Pairs]) :-
 | 
						|
	keys_values_pairs(Ks, Vs, Pairs).
 | 
						|
 | 
						|
values_keys_pairs([], [], []).
 | 
						|
values_keys_pairs([V|Vs], [K|Ks], [K-V|Pairs]) :-
 | 
						|
	values_keys_pairs(Vs, Ks, Pairs).
 | 
						|
 | 
						|
%%	pairs_values(+Pairs, -Values) is det.
 | 
						|
%
 | 
						|
%	Remove the keys  from  a  list   of  Key-Value  pairs.  Same  as
 | 
						|
%	pairs_keys_values(Pairs, _, Values)
 | 
						|
 | 
						|
pairs_values([], []).
 | 
						|
pairs_values([_-V|T0], [V|T]) :-
 | 
						|
	pairs_values(T0, T).
 | 
						|
 | 
						|
 | 
						|
%%	pairs_keys(+Pairs, -Keys) is det.
 | 
						|
%
 | 
						|
%	Remove the values  from  a  list   of  Key-Value  pairs.  Same  as
 | 
						|
%	pairs_keys_values(Pairs, Keys, _)
 | 
						|
 | 
						|
pairs_keys([], []).
 | 
						|
pairs_keys([K-_|T0], [K|T]) :-
 | 
						|
	pairs_keys(T0, T).
 | 
						|
 | 
						|
 | 
						|
%%	group_pairs_by_key(+Pairs, -Joined:list(Key-Values)) is det.
 | 
						|
%
 | 
						|
%	Group values with the same key.  For example:
 | 
						|
%	
 | 
						|
%	==
 | 
						|
%	?- group_pairs_by_key([a-2, a-1, b-4], X).
 | 
						|
%	
 | 
						|
%	X = [a-[2,1], b-[4]]
 | 
						|
%	==
 | 
						|
%	
 | 
						|
%	@param	Pairs	Key-Value list, sorted to the standard order
 | 
						|
%			of terms (as keysort/2 does)
 | 
						|
%	@param  Joined	List of Key-Group, where Group is the
 | 
						|
%			list of Values associated with Key. 
 | 
						|
 | 
						|
group_pairs_by_key([], []).
 | 
						|
group_pairs_by_key([M-N|T0], [M-[N|TN]|T]) :-
 | 
						|
	same_key(M, T0, TN, T1),
 | 
						|
	group_pairs_by_key(T1, T).
 | 
						|
 | 
						|
same_key(M, [M-N|T0], [N|TN], T) :- !,
 | 
						|
	same_key(M, T0, TN, T).
 | 
						|
same_key(_, L, [], L).
 | 
						|
 | 
						|
 | 
						|
%%	transpose_pairs(+Pairs, -Transposed) is det.
 | 
						|
%
 | 
						|
%	Swap Key-Value to Value-Key and sort the result on Value
 | 
						|
%	(the new key) using keysort/2.
 | 
						|
 | 
						|
transpose_pairs(Pairs, Transposed) :-
 | 
						|
	flip_pairs(Pairs, Flipped),
 | 
						|
	keysort(Flipped, Transposed).
 | 
						|
 | 
						|
flip_pairs([], []).
 | 
						|
flip_pairs([Key-Val|Pairs], [Val-Key|Flipped]) :-
 | 
						|
	flip_pairs(Pairs, Flipped).
 | 
						|
 | 
						|
 | 
						|
%%	map_list_to_pairs(:Function, +List, -Keyed)
 | 
						|
%
 | 
						|
%	Create a key-value list by mapping each element of List.
 | 
						|
%	For example, if we have a list of lists we can create a
 | 
						|
%	list of Length-List using
 | 
						|
%	
 | 
						|
%	==
 | 
						|
%		map_list_to_pairs(length, ListOfLists, Pairs),
 | 
						|
%	==
 | 
						|
 | 
						|
:- meta_predicate
 | 
						|
	map_list_to_pairs(2,+,+).
 | 
						|
 | 
						|
map_list_to_pairs(Function, List, Pairs) :-
 | 
						|
	map_list_to_pairs2(List, Function, Pairs).
 | 
						|
 | 
						|
map_list_to_pairs2([], _, []).
 | 
						|
map_list_to_pairs2([H|T0], Pred, [K-H|T]) :-
 | 
						|
	call(Pred, H, K),
 | 
						|
	map_list_to_pairs2(T0, Pred, T).
 | 
						|
 |