Function F:递归函数:连接两个列表之间的公共值

Function F:递归函数:连接两个列表之间的公共值,function,recursion,f#,helper,tail-recursion,Function,Recursion,F#,Helper,Tail Recursion,这就是我现在所拥有的,但我已经尝试了很多不同的事情。memberof接受一个浮点列表和一个浮点,如果浮点是浮点列表的成员,则返回true。函数的成员工作。我不知道如何返回新列表 我还有一个隔离函数,它将获取一个列表并删除列表中的任何重复浮动。这似乎有帮助 编辑:我试图弄清楚当xs=[]时如何返回新列表。答案是正确的,直到common,它不返回列表中的公共成员,而是包含所有元素的串联列表 示例我希望common生成以下结果: [1.0;2.0;3.0;4.0;5.0][4.0;3.0;9.0]->

这就是我现在所拥有的,但我已经尝试了很多不同的事情。memberof接受一个浮点列表和一个浮点,如果浮点是浮点列表的成员,则返回true。函数的成员工作。我不知道如何返回新列表

我还有一个隔离函数,它将获取一个列表并删除列表中的任何重复浮动。这似乎有帮助


编辑:我试图弄清楚当xs=[]时如何返回新列表。答案是正确的,直到common,它不返回列表中的公共成员,而是包含所有元素的串联列表

示例我希望common生成以下结果:

[1.0;2.0;3.0;4.0;5.0][4.0;3.0;9.0]->[3.0;4.0]

而不是“普通”生产:

[1.0;2.0;3.0;4.0;5.0][4.0;3.0;9.0]->[1.0;2.0;3.0;4.0;5.0;9.0]


如何使用递归解决此问题?

因此,要使用列表递归解决此问题,您需要以下内容:

let rec common a b =
    match isolate(a) b with
    | (x::xs,isolate(b)) ->
        if memberof(b x) then [x,common(xs b)]
        else common(xs b)
注意,我已经从递归函数中删除了隔离,它只需要在开始时执行一次

因为您没有发布隔离函数或memberof函数的代码,所以我不想对其他问题中的代码进行假设,否则这个答案对其他任何人都没有用处。当然,您可以自由地使用相同函数的不同实现

我只是做了以下简单的定义:

let common a b =
    let rec commonRec a b =
        match a with
        | [] -> [] // a is empty : no elements can be common so return empty list
        | x::xs ->
            if memberof x b then x :: commonRec xs b // if x is a member of b, keep it
            else commonRec xs b // otherwise continue with remaining elements
    commonRec (isolate a) (isolate b) // remove duplicates here
结果:

[1.0;2.0;3.0;4.0;5.0] [4.0; 3.0; 9.0] -->[3.0;4.0]


就我所理解的这个函数的需求而言,它应该返回两个列表的集合。由于这是一个基于集合的操作,它已经内置到F中:

let isolate lst =
    lst |> Set.ofList |> Set.toList

let memberof a list =
    List.contains a list

以我刚才给你的报告提供的例子为基础

注意:这基本上与by theinerlight相同,我只是使用了前面问题中提到的格式,并给出了所有所需函数的示例

由于您似乎没有使用此格式,因此我将介绍我用于使函数通用的步骤

> set [1.0;2.0;3.0;4.0;5.0] |> Set.intersect (set [4.0;3.0;9.0]);;
val it : Set<float> = set [3.0; 4.0]
并将函数命名为common

公共需要两个输入列表和一个输出列表。 首先我们将设置签名,然后将这两个列表传递给commonInner。 在这一点上,我还没有决定如何处理这两个列表,我知道我需要它们来执行转换函数。 由于输出将来自累加器,并且是一个列表,因此我们使用commonInner a b[]中的空列表初始化累加器

现在,我们可以决定如何将两个列表转换为一个列表,其中包含两个列表共有的项。由于最终列表不会有重复项,所以让我们使用isolate将每个列表单独转换为唯一项的列表

此时,当我们到达match语句时,我们有两个列表。我们只需要将一个列表中的每个项目与另一个列表中的项目进行比较,当它们相同时,对该项目进行处理

使用函数式编程时,我们必须意识到列表是有用的,并将其用于我们的利益。不可变的是不能更改的,您不能向其添加、删除,甚至更改其值。现在您可能会问,为什么我可以添加到列表中,这在代码中一直都是这样做的。答案是原始列表保留在堆栈上,并使用原始列表和要添加的项构造新列表。是的,这是比必要的更多的工作,但这就是它的工作原理。从我的角度来看,关于代码的可证明性,它值得付出代价。因此,要获得输出列表,最好从空列表开始创建列表,而不是修改现有列表。这就是为什么在我给出的示例中,您从未看到delete函数

因此,我们知道如何使用递归分别查看列表中的每个项目。如果这没有意义,那么就在一些不同类型的列表上使用它,只打印值。对于大多数人来说,学习递归就是其中之一,如果你挣扎了一段时间,然后突然得到了它

let common (a : 'a list) (b : 'a list) : 'a list =
    let aUnique = isolate a
    let bUnique = isolate b
    let rec commonInner a b acc =
        match list with
        | head :: tail ->
            let acc = (somefunc head) :: acc
            commonInner tail acc
        | [] -> acc
    commonInner aUnique bUnique  []
当我们有一个头像和另一个b名单时,我们必须做出决定

这让我们想到了这一点

if (memberof b hd) the
当a的磁头在列表b中时,我们希望将其添加到累加器acc中,acc将成为输出列表。 当a的磁头不在列表b中时,我们不想将其添加到累加器acc中,acc将成为输出列表

let common (a : 'a list) (b : 'a list) : 'a list =
    let aUnique = isolate a
    let bUnique = isolate b
    let rec commonInner a b acc =
        match list with
        | head :: tail ->
            if (memberof b head) then
                do something
                commInner tail acc
            else
                do something different
                commonInner tail acc
        | [] -> acc
    commonInner aUnique bUnique  []
最后,由于使用了:,累加器的输出列表的顺序是向后的,所以在返回结果之前,我们只使用reverse来反转列表

let common (a : 'a list) (b : 'a list) : 'a list =
    let aUnique = isolate a
    let bUnique = isolate b
    let rec commonInner a b acc =
        match list with
        | head :: tail ->
            if (memberof b head) then
                let acc = head :: acc
                commInner tail acc
            else
                commonInner tail acc
        | [] -> acc
    commonInner aUnique bUnique  []
这是工作代码

let common (a : 'a list) (b : 'a list) : 'a list =
    let aUnique = isolate a
    let bUnique = isolate b
    let rec commonInner a b acc =
        match list with
        | head :: tail ->
            if (memberof b head) then
                let acc = head :: acc
                commInner tail acc
            else
                commonInner tail acc
        | [] -> reverse acc
    commonInner aUnique bUnique  []

可能的重复项我正在尝试找出当xs=[]时如何返回新列表。在这个线程中,答案是正确的,直到common,它不返回列表中的公共成员,而是包含所有元素的串联列表。set[1.0;2.0;3.0;4.0;5.0]|>set.intersect set[4.0;3.0;9.0]?@MarkSeemann这就是逻辑方法b
但这听起来像是列表的递归。@TheInnerLight我也有这种感觉,我也认为我能猜出原因,但我认为应该在OP中明确说明,而事实并非如此。几年后,有人可能会通过互联网搜索找到这个问题及其答案,到那时,背景早已不复存在。
if (memberof b hd) the
let common (a : 'a list) (b : 'a list) : 'a list =
    let aUnique = isolate a
    let bUnique = isolate b
    let rec commonInner a b acc =
        match list with
        | head :: tail ->
            if (memberof b head) then
                do something
                commInner tail acc
            else
                do something different
                commonInner tail acc
        | [] -> acc
    commonInner aUnique bUnique  []
let common (a : 'a list) (b : 'a list) : 'a list =
    let aUnique = isolate a
    let bUnique = isolate b
    let rec commonInner a b acc =
        match list with
        | head :: tail ->
            if (memberof b head) then
                let acc = head :: acc
                commInner tail acc
            else
                commonInner tail acc
        | [] -> acc
    commonInner aUnique bUnique  []
let common (a : 'a list) (b : 'a list) : 'a list =
    let aUnique = isolate a
    let bUnique = isolate b
    let rec commonInner a b acc =
        match list with
        | head :: tail ->
            if (memberof b head) then
                let acc = head :: acc
                commInner tail acc
            else
                commonInner tail acc
        | [] -> reverse acc
    commonInner aUnique bUnique  []
// Reverse the order of the items in a list.

// val reverse : l:'a list -> 'a list
let reverse l =
    let rec reverseInner l acc =
        match l with
        | x::xs -> 
            let acc = x :: acc
            reverseInner xs acc
        | [] -> acc
    reverseInner l []

// Predicate that returns true if item is a member of the list.

// val memberof : l:'a list -> item:'a -> bool when 'a : equality
let memberof l item =
    let rec memberInner l item =
        match l with
        | x::xs -> 
            if x = item then
                true
            else 
                memberInner xs item
        | [] -> false
    memberInner l item


// Return a list of unique items.

// val isolate : list:'a list -> 'a list when 'a : equality
let isolate list =
    let rec isolateInner searchList commonlist =
        match searchList with
        | x::xs ->
            if (memberof commonlist x) then
                isolateInner xs commonlist
            else
                let commonlist = (x :: commonlist)
                isolateInner xs commonlist
        | [] -> reverse commonlist
    isolateInner list []

// val common : a:'a list -> b:'a list -> 'a list when 'a : equality
let common a b =
    let aUnique = isolate a
    let bUnique = isolate b
    let rec commonInner a b acc =
        match a with
        | x::xs ->
            if memberof b x then
                let acc = x :: acc
                commonInner xs b acc
            else
                commonInner xs b acc
        | [] -> reverse acc
    commonInner aUnique bUnique []

common [1.0;2.0;3.0;4.0;5.0] [4.0;3.0;9.0]      // val it : float list = [3.0; 4.0]