将C#代码转换为F#代码:列出操作 [英] Convert C# code to F# code: lists manipulation
问题描述
早上好, 首先,我介绍一下自己:我叫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屋!