Заменить кортежи в списке

Итак, у меня есть следующий список кортежей:

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

1 ответ

Решение

Ваше описание не совсем совпадает с вашим вторым примером. Вы сказали, что хотите заменить значение первым дубликатом, но во втором примере вы заменили (3,"l") с последним дубликатом ((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 [];

Эта функция работает как и ожидалось для ваших двух примеров.

Для полноты, вот подход, в котором это первое дублированное значение, которое в конечном итоге сохраняется. Для этого добавьте логический флаг, который сообщит вам, было ли обновлено значение. При первом обновлении - установите флаг. Снимите флажки в конечном результате:

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. Код, который я привел выше, ужасно неэффективен, в конечном итоге структура данных с O(n) уважать.

Другие вопросы по тегам