f # Поиск разницы между двумя списками obj []

У меня есть 2 списка obj [] list1 и list2. List1 имеет длину 8, а list2 - 10. В списке list1 есть массивы, которые существуют только в list1. То же самое и со списком 2. Но есть массивы, которые существуют в обоих. Мне интересно, как получить массивы, существующие в list1. В тот момент, когда я запускаю свой код, я получаю список массивов, которые существуют в обоих списках, но в нем отсутствуют данные, уникальные для list1. Мне интересно, как получить эти уникальные данные list1. Какие-либо предложения?

let getProdOnly (index:int)(list1:obj[]list)(list2:obj[]list) =
    let mutable list3 = list.Empty
    for i = 0 to list1.Length-1 do
        for j = 0 to list2.Length-1 do
            if list1.Item(i).GetValue(index).Equals(list2.Item(j).GetValue(index)) then
                System.Diagnostics.Debug.WriteLine("Exists in List 1 and 2")
            else
                list3 <- list1.Item(i)

person Mark    schedule 17.10.2016    source источник
comment
Возможный дубликат F # Seq diff   -  person franssu    schedule 17.10.2016
comment
Индексирование в список F #! Ох, мои глаза!   -  person Joel Mueller    schedule 17.10.2016


Ответы (3)


Что-то вроде этого:

let ar1 = [|1;2;3|]
let ar2 = [|2;3;4|]
let s1 = ar1 |> Set.ofArray
let s2 = ar2 |> Set.ofArray
Set.difference s1 s2
//val it : Set<int> = set [1]

Также существует куча Array связанных функций, например compareWith, independent, существует, если вы хотите работать с массивами напрямую.

Но, как указывалось в предыдущих ответах, этот тип императивного кода не очень идиоматичен. Старайтесь избегать изменяемых переменных, старайтесь избегать циклов. Его, вероятно, можно было бы переписать, например, на Array.map.

person s952163    schedule 17.10.2016
comment
Это не предполагает повторяющихся значений. Если необходимо сохранить повторяющиеся значения, то ответом будут наборы мощности или что-то еще. Но, насколько мне известно, в F3 для этого нет собственной библиотеки. - person Helge Rene Urholm; 18.10.2016
comment
@HelgeReneUrholm Я согласен. Все зависит от данных и намерений. Конечно, можно просто проверить каждый входной массив и накапливать результаты. - person s952163; 18.10.2016

Если вы хотите, чтобы элементы были уникальными для одного списка, это самый простой способ сделать это в F # 4.0:

list1
|> List.except list2 

который удалит все элементы list2 из list1. Обратите внимание, что except также вызывает отдельный объект, поэтому вам может потребоваться остерегаться этого.

person Ringil    schedule 17.10.2016

Сначала я взял ваш код с небольшими изменениями и добавил отладку printf, чтобы посмотреть, что он делает.

let getProdOnly2 (index:int)(list1:obj[] list)(list2:obj[] list) =
    let mutable list3 : obj[] list= list.Empty
    for i = 0 to list1.Length-1 do
        for j = 0 to list2.Length-1 do
            if list1.[i].[index] = list2.[j].[index] then
                printfn "equal"
                System.Diagnostics.Debug.WriteLine("Exists in List 1 and 2")
                list3
            else
                printfn "add %A %A"  (list1.Item(i)) (list2.Item(j)) 
                list3 <- list1.Item(i) :: list3
                list3
    list3

И он добавляет элемент каждый раз, когда находит элемент, не равный текущему элементу. Итак, моя попытка состоит в том, чтобы взять list1 и просто сохранить или лучше отфильтровать элементы, которые не являются частью list2.

let getProdOnly3 (index:int)(list1:obj[] list)(list2:obj[] list) =
    list1
    |> List.filter (fun el1 ->
        list2
        |> List.fold (fun acc el2 -> acc && (el2<>el1))  true )

Я протестировал код со следующими списками

let list1 = [   [| 1;2;3;4|]
                [| 1;2;3;4|] 
                [| 2;3;4|]
                [| 3;4;5|] ] |> List.map (fun a -> a |> Array.map (fun e -> box e))

let list2 = [   [| 2;3;4|]
                [| 3;4;5|] ] |> List.map (fun a -> a |> Array.map (fun e -> box e))

В отличие от s952163 мой результат будет иметь двойные записи, если list1 имеет двойные записи, не знаю, желательно ли это или нежелательно, beahyuvier.

person Peter Siebke    schedule 17.10.2016