将C#代码转换为F#代码:列出操作 [英] Convert C# code to F# code: lists manipulation

查看:79
本文介绍了将C#代码转换为F#代码:列出操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

早上好, 首先,我介绍一下自己:我叫Mattia,我是计算机科学专业的学生.

我已经用其他两种编程语言(C#和Python)实现了三个函数的问题,使用for和while这样的命令式循环,但是我要做的是在递归中转换它们样式.

C#中的函数是:

  • resetList:给定两个列表,该方法将计数器初始化在第一个列表的对象内,然后将新对象放入第二个列表.

    public static List<myObject> resetList(List<myObject> inList, List<myObject> outList, bool flag)
    {
        foreach (myObject myObj in inList)
        {
            myObj.FirstCounter= 0;
    
            if (flag)
                myObj.SecondCounter= 0;
            outList.Add(myObj );
        }
        return outList;
    }
    

  • randomIntList:给定要生成的整数数量(n),该方法返回一个列表,其中包含从1到56之间选择的n个随机整数.

    int i = 0;
    while (i < n)
    {
        int randomNumber = randomizer.Next(1, 56 + 1);
    
        if (!listOut.Contains(randomNumber))
        {
            listOut[I] = randomNumber;
            i++;
        }
    }
    

  • compareRule:给定两个自定义对象,该方法将找到它们之间的第一个相等字符.

    int index = myObject1.Index;
    char myChar = myObject1.getChar();
    
    while ((index < 6) && !(myObject2.getChar().Equals(myChar)))
    {
        index++;
        myChar= myObject1.getCharAt(index);
    }
    
    myObject1.Counter++;
    

我可以将它们转换为命令式循环样式,但不能以递归样式转换,例如:

  • resetList:

    (Imperative version)
    
    let resetList inList flag =
        let mutable outList = []
    
        for myObj in inList do
            if flag = true then
                outList <- outList @ [new myObject(myObj.Index, 0, myObj.Chars, 0)]
            else
                outList <- outList @ [new myObject(myObj.Index, 0, myObj.Chars, myObj.Counter)]
    outList
    
    (Recursive version: try...)
    
    let resetList listaIn flag =
        let mutable outList = []
    
        let rec resetListRec inList =
            match inList with
            | [] -> outList
            | head :: tail ->
                if flag = true then
                    outList <- outList @ [new myObject(head.Index, 0, head.Chars, 0)]
                else
                    outList <- outList @ [new myObject(head.Index, 0, head.Chars, head.Counter)]
        resetListRec tail
    

谢谢你,玛蒂亚(Mattia).

解决方案:

  • resetList:

    let rec resetList list flag =
        match list with
        | [] -> []
        | (myObj : myObject) :: myObjs ->
            let myObj =
                if flag then
                   new myObject(myObj.Index, 0, myObj.Chars, 0)
                else
                   new myObject(myObj.Index, 0, myObj.Chars, myObjs.Counter)
    
        myObj :: (resetList myObjs flag)
    

  • findCharEqual:

    let rec findCharEqual index (myObj1 : myObject) (myObj2 : myObject) = 
        let char1 = myObj1.GetChar()
        let char2 = myObj1.GetChar(index)
    
        if (index < 6) && (char1 <> char2) then
            findCharEqual (index + 1) myObj1 myObj2
        else
            new myObject(myObj2.Index, index, myObj2.Chars, myObj2.Counter + 1)
    

  • randomList:

    let randomList n = 
        let randomizer = new Random()
        Seq.initInfinite (fun _ -> randomizer.Next(1, MAX_N + 1))
        |> Seq.distinct 
        |> Seq.take n
        |> Seq.toList
    

更新:现在,我正在使用这个(最后一个)while循环,尝试以递归形式进行翻译.

(... declaration of listIn, listOut, listTemp...)

while (listOut.Length < n) do
    let mutable myObj1 = new myObject(0, 0, Array.empty, 0)
    let mutable myObj2 = new myObject(0, 0, Array.empty,0)

    if (listIn.Length = 0) then
        if (listOut.Length > 1) then
            myObj1 <- listOut.[listOut.Length - 2]

            myObj2 <- new myObject(listOut.[listOut.Length - 1].Index, listOut.[listOut.Length - 1].Char + 1, listOut.[listOut.Length - 1].Chars, listOut.[listOut.Length - 1].Counter)

            listOut <- removeObject (listOut.Length - 1) listOut

            if (myObj2.Counter < 2) then
                listIn <- listIn @ resetObject listTemp false
                listTemp <- List.empty<myObject>

            else
                myObj1 <- new myObject(listOut.Head.Index, listOut.Head.Char + 1, listOut.Head.Chars, listOut.Head.Counter)

                listOut <- List.empty<myObject>
                listOut <- listOut @ [myObj1]

                listIn <- listIn @ resetObject listTemp true

                listTemp <- List.empty<myObject>

                myObj2 <- listIn.Head
                listIn <- removeObject 0 listIn
        else
            myObj1 <- listOut.[listOut.Length - 1]
            myObj2 <- listIn.Head

            listIn <- removeObject 0 listIn

        let mutable indFxDx = myObj2.Char
        myObj2 <- fingEqualChar indFxDx myObj1 myObj2

        if (myObj2.Char < 6) then
            if (myObj1.leftChar = myObj2.rightChar) then
                listOut <- listOut @ [myObj2]

                if (listTemp.Length > 0) then
                    listIn <- listIn @ resetObject listTemp false
                    listTemp <- List.empty<myObject>

        else
            listTemp <- listTemp @ [myObj2]

(...无效的解决方案...)

(... declaration of listIn, listOut, listTemp...)
let rec findSolution i =
    if i < n then
        (... function atre the while declaration, to the end...)
    findSolution (i + 1)

listOut <- findSolution 0

问题是我需要修改三个列表,并且以递归方式无法实现,所以大家有什么主意吗?

马蒂亚

解决方案

如果您正在学习F#,那么首先自己编写一些递归函数会很有用.稍后,您将了解到它们中的许多都与某些现有模式匹配,并且您将使用List.map之类的功能(如在Ankur的解决方案中一样).

因此,要递归编写resetList函数,您将执行以下操作:

let rec resetList inList flag =
    match inList with
    | [] -> []  // For empty list, we can only return emtpy list
    | x::xs ->  
        // For non-empty list, create an object depending on the 'flag'
        let obj =
          if flag then new myObject(myObj.Index, 0, myObj.Chars, 0)
          else new myObject(myObj.Index, 0, myObj.Chars, myObj.Counter)
        // Process the rest of the list (recursively) and then add 
        // object we just created to the front
        obj :: (resetList xs flag)

此实现不是 tail-recursive ,这意味着它在递归调用restList之后会执行一些操作(它将值附加到前面).如果您要处理长列表,这可能是个问题,但是您现在可能不必担心.

有关详细信息,请参阅使用功能列表的一些介绍,请参见此MSDN文章. >

Good morning at all, first I present myself: my name is Mattia and I'm a student in Computer Science.

I've a problem with three function that I've already implement in two other programming language (C# and Python), using imperative loop like for and while, but what I've to do is to convert them in the recursive style.

The function in C# are:

  • resetList: given two list, the method initialize the counters inside the object of first list, and put the new object in the second list.

    public static List<myObject> resetList(List<myObject> inList, List<myObject> outList, bool flag)
    {
        foreach (myObject myObj in inList)
        {
            myObj.FirstCounter= 0;
    
            if (flag)
                myObj.SecondCounter= 0;
            outList.Add(myObj );
        }
        return outList;
    }
    

  • randomIntList: given the number of integer to generate (n), the method return a list with n random integer choosen between 1 and 56.

    int i = 0;
    while (i < n)
    {
        int randomNumber = randomizer.Next(1, 56 + 1);
    
        if (!listOut.Contains(randomNumber))
        {
            listOut[I] = randomNumber;
            i++;
        }
    }
    

  • compareRule: given two custom object, the method find the first equal character between them.

    int index = myObject1.Index;
    char myChar = myObject1.getChar();
    
    while ((index < 6) && !(myObject2.getChar().Equals(myChar)))
    {
        index++;
        myChar= myObject1.getCharAt(index);
    }
    
    myObject1.Counter++;
    

I can convert them in imperative loop style but not in recursive style, for example:

  • resetList:

    (Imperative version)
    
    let resetList inList flag =
        let mutable outList = []
    
        for myObj in inList do
            if flag = true then
                outList <- outList @ [new myObject(myObj.Index, 0, myObj.Chars, 0)]
            else
                outList <- outList @ [new myObject(myObj.Index, 0, myObj.Chars, myObj.Counter)]
    outList
    
    (Recursive version: try...)
    
    let resetList listaIn flag =
        let mutable outList = []
    
        let rec resetListRec inList =
            match inList with
            | [] -> outList
            | head :: tail ->
                if flag = true then
                    outList <- outList @ [new myObject(head.Index, 0, head.Chars, 0)]
                else
                    outList <- outList @ [new myObject(head.Index, 0, head.Chars, head.Counter)]
        resetListRec tail
    

Thank you at all, Mattia.

Solutions:

  • resetList:

    let rec resetList list flag =
        match list with
        | [] -> []
        | (myObj : myObject) :: myObjs ->
            let myObj =
                if flag then
                   new myObject(myObj.Index, 0, myObj.Chars, 0)
                else
                   new myObject(myObj.Index, 0, myObj.Chars, myObjs.Counter)
    
        myObj :: (resetList myObjs flag)
    

  • findCharEqual:

    let rec findCharEqual index (myObj1 : myObject) (myObj2 : myObject) = 
        let char1 = myObj1.GetChar()
        let char2 = myObj1.GetChar(index)
    
        if (index < 6) && (char1 <> char2) then
            findCharEqual (index + 1) myObj1 myObj2
        else
            new myObject(myObj2.Index, index, myObj2.Chars, myObj2.Counter + 1)
    

  • randomList:

    let randomList n = 
        let randomizer = new Random()
        Seq.initInfinite (fun _ -> randomizer.Next(1, MAX_N + 1))
        |> Seq.distinct 
        |> Seq.take n
        |> Seq.toList
    

Update: Now I'm working with this (last) while loop that I'm trying to translate in recursive form.

(... declaration of listIn, listOut, listTemp...)

while (listOut.Length < n) do
    let mutable myObj1 = new myObject(0, 0, Array.empty, 0)
    let mutable myObj2 = new myObject(0, 0, Array.empty,0)

    if (listIn.Length = 0) then
        if (listOut.Length > 1) then
            myObj1 <- listOut.[listOut.Length - 2]

            myObj2 <- new myObject(listOut.[listOut.Length - 1].Index, listOut.[listOut.Length - 1].Char + 1, listOut.[listOut.Length - 1].Chars, listOut.[listOut.Length - 1].Counter)

            listOut <- removeObject (listOut.Length - 1) listOut

            if (myObj2.Counter < 2) then
                listIn <- listIn @ resetObject listTemp false
                listTemp <- List.empty<myObject>

            else
                myObj1 <- new myObject(listOut.Head.Index, listOut.Head.Char + 1, listOut.Head.Chars, listOut.Head.Counter)

                listOut <- List.empty<myObject>
                listOut <- listOut @ [myObj1]

                listIn <- listIn @ resetObject listTemp true

                listTemp <- List.empty<myObject>

                myObj2 <- listIn.Head
                listIn <- removeObject 0 listIn
        else
            myObj1 <- listOut.[listOut.Length - 1]
            myObj2 <- listIn.Head

            listIn <- removeObject 0 listIn

        let mutable indFxDx = myObj2.Char
        myObj2 <- fingEqualChar indFxDx myObj1 myObj2

        if (myObj2.Char < 6) then
            if (myObj1.leftChar = myObj2.rightChar) then
                listOut <- listOut @ [myObj2]

                if (listTemp.Length > 0) then
                    listIn <- listIn @ resetObject listTemp false
                    listTemp <- List.empty<myObject>

        else
            listTemp <- listTemp @ [myObj2]

(... A not working solution ...)

(... declaration of listIn, listOut, listTemp...)
let rec findSolution i =
    if i < n then
        (... function atre the while declaration, to the end...)
    findSolution (i + 1)

listOut <- findSolution 0

The problem is that I need to modify three lists and in the recursive style this is not possible, sombody have any idea?

Mattia

解决方案

If you're learning F# then it is useful to first write a few recursive functions yourself. Later, you'll learn that many of them match some existing pattern and you'll use functions like List.map (as in Ankur's solution).

So, to write your resetList function recursively, you would do something like this:

let rec resetList inList flag =
    match inList with
    | [] -> []  // For empty list, we can only return emtpy list
    | x::xs ->  
        // For non-empty list, create an object depending on the 'flag'
        let obj =
          if flag then new myObject(myObj.Index, 0, myObj.Chars, 0)
          else new myObject(myObj.Index, 0, myObj.Chars, myObj.Counter)
        // Process the rest of the list (recursively) and then add 
        // object we just created to the front
        obj :: (resetList xs flag)

This implementation is not tail-recursive, which means that it does something after calling restList recursively (it appends value to the front). This can be a problem if you're processing long lists, but you probably don't need to worry at the moment.

For more information & some introduction to working with functional lists, see this MSDN article.

这篇关于将C#代码转换为F#代码:列出操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆