163 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
		
		
			
		
	
	
			163 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
|   | /*  $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 | ||
|  | 
 | ||
|  | 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), | ||
|  | %	== | ||
|  | 
 | ||
|  | :- module_transparent | ||
|  | 	map_list_to_pairs/3, | ||
|  | 	map_list_to_pairs2/3. | ||
|  | 
 | ||
|  | 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). | ||
|  | 
 |