问题:
给出一个项目列表,例如:
["5";"10";"2";"53";"4"]
和搜索索引,我需要一个函数,它将当前给定的索引与其邻居进行比较,返回最大的索引
示例:
目前这是我的功能。它不编译:
let GetMaxNode (x:Array) Idx = if x.[Idx] > x.[Idx+1] then Idx else If x.[Idx] < x.[Idx+1] then Idx+1
我得到的所有x'的错误是:
The field, constructor or member 'Item' is not defined (FS0039)
还有第二个If:
The value or constructor 'If' is not defined (FS0039)
我怀疑我仍在以程序方式思考,我正在考虑使用模式匹配,但是我对语法没有足够的信心来尝试它。
请你也解释答案,因为我正在努力学习F#,只是解决方案对我没什么帮助。
答案 0 :(得分:3)
以下是一些基于你的代码:
let GetMaxNode (x:_[]) idx =
if x.[idx] > x.[idx+1] then
idx
elif x.[idx] < x.[idx+1] then
idx+1
else
idx // same, return this one
主要变化是
<typename> []
。在这种情况下,我们不关心类型,所以我使用_
作为“不关心,请为我推断正确的”类型变量。elif
在F#else
个案
答案 1 :(得分:3)
很难在函数式中为您的问题编写解决方案,因为您的问题是根据索引定义的 - 当使用功能数据结构(例如列表)时,您通常不会通过索引引用元素。
例如,问题的功能版本是,当当前位置的元素大于下一个元素时,创建一个包含true
的列表,当它小时,创建false
。对于您的数据,这将给出:
let data = [ 5; 10; 2; 53; 4 ]
let res = [ false; true; false; true; ] // no item to compare '4' with
使用遍历列表和模式匹配的递归函数可以很好地解决这个问题(因为模式匹配对于函数列表比使用数组更好)
let rec getMaxNodes data =
match data with
// list has at least two elements and current is larger
| current::next::other when current >= next ->
// process the rest of the list
let rest = (getMaxNodes (next::other))
// return 'true' followed by recursively processed rest of the list
true::rest
// list has at least two elements and current is smaller
| current::next::rest ->
// same as the previous case, but we return false
false::(getMaxNodes (next::rest))
| _ ->
// one element (so we cannot compare it with the next one)
// or empty list, so we return empty list
[]
getMaxNodes data
答案 2 :(得分:2)
以下是Brian回答的模式匹配版本。
let GetMaxNode (x:_[]) idx =
match idx with
| idx when x.[idx] > x.[idx+1] -> idx
| idx when x.[idx] < x.[idx+1] -> idx + 1
| idx -> idx // same, return this one
当您查看更多F#代码时,您可能还会看到语法快捷方式。以下代码在功能上与上面的代码完全相同。
let GetMaxNode (x:_[]) = function
| idx when x.[idx] > x.[idx+1] -> idx
| idx when x.[idx] < x.[idx+1] -> idx + 1
| idx -> idx // same, return this one
答案 3 :(得分:0)
每当你开始讨论索引时,你最好坚持使用Arrays或ResizeArrays; F#列表不适合索引上的操作,因为它们是从头到尾单链接的。话虽如此,通过使用递归循环遍历列表并跟踪当前索引和当前元素,以纯函数方式编写此算法并不困难。
let find elements index =
//a local tail-recursive function hides implementation details
//(cur::tail) is a pattern match on the list, i is the current index position
let rec loop (cur::tail) i =
if i = index then //when the current index matches the search index
if cur >= tail.Head then i //compare cur to tail.Head (which is next)
else (i+1)
else loop tail (i+1) //else continue
loop elements 0 //the entry point of loop and our return value
使用整数列表而不是字符串来获得您期望的结果(因为“10”实际上小于“5”):
> let x = [5;10;2;53;4];;
> find x 0;;
val it : int = 1
> find x 1;;
val it : int = 1
> find x 2;;
val it : int = 3
> find x 3;;
val it : int = 3