Your description doesn't quite mesh with your second example. You said that you wanted to replace the value with the first duplicate but in your second example you replaced (3,"l")
with the last duplicate ((3,"f")
rather than (3,"x")
). Both can be done, though replacing by the last duplicate is significantly easier.
To replace by the last duplicate, view the final list as being obtained by updating an unambiguous list of key-value pairs. Write a function which does this update, and then run this update function on the list, starting with the empty list:
fun update (i,c) [] = [(i,c)]
| update (i,c) ((j,d)::records) =
if i = j then
(i,c)::records
else
(j,d) :: (update (i,c) records)
fun updateAll [] records = records
| updateAll ((i,c)::pairs) records = updateAll pairs (update (i,c) records)
fun removeVarDuplicates pairs = updateAll pairs [];
This function works as expected for your two examples.
For completeness, here is an approach in which it is the first duplicated value which is ultimately retained. To do this, add a Boolean flag which will tell you if the value has been updated. The first time you update -- set the flag. Strip away the flags in the final result:
fun update (i,c) [] = [(i,c,false)]
| update (i,c) ((j,d,t)::triples) =
if i = j then
if t then (j,d,t) :: triples else (j,c,true)::triples
else
(j,d,t) :: (update (i,c) triples)
fun updateAll [] triples = triples
| updateAll ((i,c)::pairs) triples = updateAll pairs (update (i,c) triples)
fun removeVarDuplicates pairs =
let
val triples = updateAll pairs []
in
map (fn (x,y,_) => (x,y)) triples
end;
When this is run against your second example:
- val mylist = [(1,"h"),(3,"l"),(45,"j"),(3, "x"), (3, "f")];
val mylist = [(1,"h"),(3,"l"),(45,"j"),(3,"x"),(3,"f")] : (int * string) list
- removeVarDuplicates mylist;
val it = [(1,"h"),(3,"x"),(45,"j")] : (int * string) list
The first value of the first duplicate key "x"
is retained rather than value for the second duplicate key.
For any serious work involving keys and values you should consider using a different data structure such as SML/NJ's hash table . The code I gave above is frightfully inefficient with the final result a data structure with O(n)
lookup.