【问题标题】:Replace tuples in a list替换列表中的元组
【发布时间】:2017-02-15 07:46:07
【问题描述】:

所以我有一个元组列表如下:

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);

【问题讨论】:

    标签: sml smlnj


    【解决方案1】:

    您的描述与您的第二个示例不太吻合。您说您想用 first 重复值替换该值,但在第二个示例中,您将 (3,"l") 替换为 last 重复值((3,"f") 而不是 (3,"x") )。两者都可以完成,尽管用最后一个副本替换要容易得多。

    要替换为最后一个副本,请查看通过更新明确的键值对列表获得的最终列表。编写一个执行此更新的函数,然后在列表上运行此更新函数,从空列表开始:

    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 [];
    

    此函数对您的两个示例按预期工作。

    为了完整起见,这是一种方法,其中 first 重复值最终被保留。为此,请添加一个布尔标志,该标志将告诉您该值是否已更新。第一次更新 - 设置标志。去掉最终结果中的标志:

    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) 查找的数据结构。

    【讨论】:

    • 很抱歉在OP中不清楚,我也可以改写这个问题。在您提供的第二个代码示例中,列表以 (3, "x") 结尾,而它应该以 (3, "f") 结尾
    • @rshah 第一个代码将返回一个带有 `(s,"f")' 的列表。正如我所说,有两种方法可以阅读您的问题,所以我都回答了​​。我怀疑第一个解释(基于您的示例)是预期的解释,但认为弄清楚如何保留第一个而不是最后一个副本会很有趣。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-14
    • 2023-04-02
    • 1970-01-01
    • 2013-10-22
    • 2019-11-24
    • 1970-01-01
    • 2014-05-29
    相关资源
    最近更新 更多