(* Copyright (C) 2000, HELM Team. * * This file is part of HELM, an Hypertextual, Electronic * Library of Mathematics, developed at the Computer Science * Department, University of Bologna, Italy. * * HELM 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. * * HELM 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 HELM; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * For details, see the HELM World-Wide-Web page, * http://cs.unibo.it/helm/. *) (* * implementazione del comando UNION *) (* (* * *) let xres_fill_context hr h1 l1 = match l1 with [] -> [] | _ -> let hh = List.combine h1 l1 in List.map (fun x -> if (List.mem_assoc x hh) then List.assoc x hh else "" ) hr ;; (* * implementazione del comando UNION *) let union_ex alist1 alist2 = let head1 = List.hd alist1 and tail1 = List.tl alist1 and head2 = List.hd alist2 and tail2 = List.tl alist2 (* e fin qui ... *) in match (head1, head2) with ([], _) -> assert false (* gli header non devono mai essere vuoti *) | (_, []) -> assert false (* devono contenere almeno [retVal] *) | (_, _) -> let headr = (head2 @ (List.find_all (function t -> not (List.mem t head2)) head1) ) in (* header del risultato finale *) List.append (* il risultato finale e' la concatenazione ...*) [headr] (* ... dell'header costruito prima ...*) (Sort.list (fun l m -> List.hd l < List.hd m) (match (tail1, tail2) with (* e di una coda "unione" *) ([], _) -> tail2 (* va bene perche' l'altra lista e' vuota *) | (_, []) -> tail1 (* va bene perche' l'altra lista e' vuota *) | (_, _) -> let first = (* parte dell'unione che riguarda solo il primo set *) List.map ( fun l -> [List.hd l] @ xres_fill_context (List.tl headr) (List.tl head1) (List.tl l) ) tail1 in List.fold_left (fun par x -> let y = (* elemento candidato ad entrare *) [List.hd x] @ xres_fill_context (List.tl headr) (List.tl head2) (List.tl x) in par @ if (List.find_all (fun t -> t = y) par) = [] then [y] else [] ) first (* List.fold_left *) tail2 (* List.fold_left *) (* first @ List.map (fun l -> [List.hd l] @ xres_fill_context (List.tl headr) (List.tl head2) (List.tl l) ) tail2 *) ) (* match *) ) ;; *) (* preserves order and gets rid of duplicates *) let rec union_ex l1 l2 = let module S = Mathql_semantics in match (l1, l2) with [],l | l,[] -> l | ({S.uri = uri1} as entry1)::tl1, ({S.uri = uri2} as entry2)::_ when uri1 < uri2 -> entry1::(union_ex tl1 l2) | ({S.uri = uri1} as entry1)::_, ({S.uri = uri2} as entry2)::tl2 when uri2 < uri1 -> entry2::(union_ex l1 tl2) | entry1::tl1,entry2::tl2 -> (* same entry *) if entry1 = entry2 then (* same attributes *) entry1::(union_ex tl1 tl2) else assert false ;; let union_ex l1 l2 = let before = Unix.time () in let res = union_ex l1 l2 in let after = Unix.time () in let ll1 = string_of_int (List.length l1) in let ll2 = string_of_int (List.length l2) in let diff = string_of_float (after -. before) in print_endline ("UNION(" ^ ll1 ^ "," ^ ll2 ^ "): " ^ diff ^ "s") ; flush stdout ; res ;;