替换列表中的元组
Replace tuples in a list
所以我有一个元组列表如下:
val mylist = [(1,"h"),(3,"l"),(45,"j"),(3, "x")] : (int * string) list
如何创建可以删除重复项的函数,但是用第一个重复项的值替换第一次出现的值?
即上面的列表将变成:
val mylist = [(1,"h"),(3,"x"),(45,"j")] : (int * string) list
如果我有列表:
val mylist = [(1,"h"),(3,"l"),(45,"j"),(3, "x"), (3, "f")] : (int * string) list
这将变成:
val mylist = [(1,"h"),(3,"f"),(45,"j")] : (int * string) list
编辑: 我创建了这个删除重复项但不替换值的函数:
fun removeVarDuplicates [] = []
| removeVarDuplicates ((v, e)::xs) = (v, e)::removeVarDuplicates(List.filter (fn (y, ys) => y <> v) xs);
您的描述与您的第二个示例不太吻合。您说您想用 first 重复项替换该值,但在第二个示例中,您将 (3,"l")
替换为 last 重复项( (3,"f")
而不是 (3,"x")
)。两者都可以完成,但用最后一个副本替换要容易得多。
要替换为最后一个副本,请将最终列表视为通过更新 key-value 对的明确列表获得的。编写一个执行此更新的函数,然后 运行 列表中的此更新函数,从空列表开始:
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 [];
对于您的两个示例,此函数按预期工作。
为了完整起见,这是一种最终保留 第一个 重复值的方法。为此,添加一个布尔标志,它会告诉您该值是否已更新。第一次更新时——设置标志。去除最终结果中的标志:
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;
当这是 运行 反对你的第二个例子时:
- 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
保留第一个重复键 "x"
的第一个值,而不是第二个重复键的值。
对于涉及键和值的任何严肃工作,您应该考虑使用不同的数据结构,例如 SML/NJ 的 hash table。我上面给出的代码非常低效,最终结果是一个具有 O(n)
查找的数据结构。
所以我有一个元组列表如下:
val mylist = [(1,"h"),(3,"l"),(45,"j"),(3, "x")] : (int * string) list
如何创建可以删除重复项的函数,但是用第一个重复项的值替换第一次出现的值?
即上面的列表将变成:
val mylist = [(1,"h"),(3,"x"),(45,"j")] : (int * string) list
如果我有列表:
val mylist = [(1,"h"),(3,"l"),(45,"j"),(3, "x"), (3, "f")] : (int * string) list
这将变成:
val mylist = [(1,"h"),(3,"f"),(45,"j")] : (int * string) list
编辑: 我创建了这个删除重复项但不替换值的函数:
fun removeVarDuplicates [] = []
| removeVarDuplicates ((v, e)::xs) = (v, e)::removeVarDuplicates(List.filter (fn (y, ys) => y <> v) xs);
您的描述与您的第二个示例不太吻合。您说您想用 first 重复项替换该值,但在第二个示例中,您将 (3,"l")
替换为 last 重复项( (3,"f")
而不是 (3,"x")
)。两者都可以完成,但用最后一个副本替换要容易得多。
要替换为最后一个副本,请将最终列表视为通过更新 key-value 对的明确列表获得的。编写一个执行此更新的函数,然后 运行 列表中的此更新函数,从空列表开始:
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 [];
对于您的两个示例,此函数按预期工作。
为了完整起见,这是一种最终保留 第一个 重复值的方法。为此,添加一个布尔标志,它会告诉您该值是否已更新。第一次更新时——设置标志。去除最终结果中的标志:
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;
当这是 运行 反对你的第二个例子时:
- 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
保留第一个重复键 "x"
的第一个值,而不是第二个重复键的值。
对于涉及键和值的任何严肃工作,您应该考虑使用不同的数据结构,例如 SML/NJ 的 hash table。我上面给出的代码非常低效,最终结果是一个具有 O(n)
查找的数据结构。