查找两个obj[]列表之间的差异

4
我有两个obj[]lists列表,list1 和 list2。List1 的长度为 8,而 list2 的长度为 10。在 list1 中有一些只存在于 list1 中的数组,同样也存在于 list2 中。但是也有一些数组同时存在于两个列表中。我想知道如何获取仅存在于 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)

1
可能是F# Seq diff的重复问题。 - franssu
4
索引 F# 列表!啊,我的眼睛! - Joel Mueller
3个回答

5
如果您想得到一个列表中独有的元素,这是在F# 4.0中最简单的方法:
list1
|> List.except list2 

这将从list1中删除所有list2的元素。请注意,except还会调用distinct,因此您可能需要注意这一点。


5

类似这样:

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、distinct、exists,如果您想直接使用数组进行操作。

但正如之前的答案所指出的那样,这种命令式代码并不是非常惯用。尽量避免可变变量,尽量避免循环。例如,可以使用Array.map来重写它。


1
这假设没有重复的值。如果要保留重复的值,则幂集或其他方法是答案。但据我所知,F3中没有本地库可用于此。 - Helge Rene Urholm
@HelgeReneUrholm 我同意。这完全取决于数据和意图。可以确保仅检查每个输入数组并累加结果。 - s952163

2

首先,我使用了您的代码并进行了一些小修改,并添加了一些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

它会在找到一个不等于当前元素时,添加一个元素。因此,我的尝试是将列表1中不是列表2的一部分的元素保留下来或过滤掉。

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有重复的条目,我的结果将会有双倍的条目,不知道这是想要的还是不想要的行为。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接