List 将C代码转换为F代码:列表操作

List 将C代码转换为F代码:列表操作,list,f#,c#-to-f#,List,F#,C# To F#,早上好, 首先我介绍我自己:我的名字叫马蒂亚,我是计算机科学专业的学生 我已经用另外两种编程语言(C#和Python)实现了三个函数,使用命令式循环,比如for和while,但我要做的是以递归方式转换它们 C#中的函数是: resetList:给定两个列表,该方法初始化第一个列表对象内的计数器,并将新对象放入第二个列表 public static List<myObject> resetList(List<myObject> inList, List<myObje

早上好, 首先我介绍我自己:我的名字叫马蒂亚,我是计算机科学专业的学生

我已经用另外两种编程语言(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;
    }
    
  • 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)
    
更新:现在我正在处理这个(最后一个)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]
(…listIn、listOut、listTemp的声明…)
而(listOut.Length1),则

myObj1以下是您可以做的事情:

let resetList inList outList flag = 
    outList @ inList |> List.map (fun i -> i.FirstCounter = 0;
                                           match flag with
                                           | true -> i.SecondCounter = 0; i
                                           | _ -> i)


let randomList n = 
    let rnd = new Random()
    seq {while true do yield rnd.Next(1,56)}
    |> Seq.distinct 
    |> Seq.take n
    |> Seq.toList 


let findCharEqual obj1 obj2 = 
    let c = obj1.getChar()
    let d = obj2.getChar()
    if c = d then
        c
    else 
        findCharEqual obj1 obj2
在迭代或递归思考之前先考虑高阶函数

如果您正在学习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)
这个实现不是尾部递归的,这意味着它在递归调用
restList
之后做了一些事情(它将值附加到前端)。如果您正在处理长列表,这可能会是一个问题,但是您现在可能不需要担心


有关更多信息和介绍。

您的第一个函数只是在一个列表上迭代,复制它并对其中的对象执行一些副作用。复制F#列表没有任何意义,因为它们是不可变的,所以惯用翻译为:

let resetList inList flag =
  for o in inList do
    o.FirstCounter <- 0
    if flag then
      o.SecondCounter <- 0
  inList
下一个
循环时相同:

let rec loop index myChar =
  if index < 6 && not (myObject2.getChar().Equals myChar) then
    myObject1.getCharAt index |> loop (index + 1)
myObject1.getChar() |> loop myObject1.Index
myObject1.Counter <- myObject1.Counter + 1
让rec循环索引myChar=
如果索引<6&¬(myObject2.getChar()等于myChar),则
myObject1.getCharAt索引|>循环(索引+1)
myObject1.getChar()|>循环myObject1.Index
myObject1.计数器
(... 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
let resetList inList outList flag = 
    outList @ inList |> List.map (fun i -> i.FirstCounter = 0;
                                           match flag with
                                           | true -> i.SecondCounter = 0; i
                                           | _ -> i)


let randomList n = 
    let rnd = new Random()
    seq {while true do yield rnd.Next(1,56)}
    |> Seq.distinct 
    |> Seq.take n
    |> Seq.toList 


let findCharEqual obj1 obj2 = 
    let c = obj1.getChar()
    let d = obj2.getChar()
    if c = d then
        c
    else 
        findCharEqual obj1 obj2
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)
let resetList inList flag =
  for o in inList do
    o.FirstCounter <- 0
    if flag then
      o.SecondCounter <- 0
  inList
let rec loop i =
  if i < n then
    let randomNumber = randomizer.Next(1, 56 + 1)
    if listOut.Contains randomNumber then
      listOut.[i] <- randomNumber
      loop (i + 1)
let rec loop index myChar =
  if index < 6 && not (myObject2.getChar().Equals myChar) then
    myObject1.getCharAt index |> loop (index + 1)
myObject1.getChar() |> loop myObject1.Index
myObject1.Counter <- myObject1.Counter + 1