为什么max(运营商)没有返回最长的列表?

时间:2015-05-27 18:17:04

标签: f# max

我想找到两个列表中最长的一个。请考虑以下代码示例:

let xs = ['B']
let ys = ['A'; 'B']
let longest = max xs ys
printfn "%A" longest

与我的预期相反,此计划的输出为['B']而不是['A'; 'B']

为什么List<'T>以这种方式实施max?这个实现的确切方式/定义在哪里?

我可以看到max需要comparison,我认为这意味着IComparable的实施。 List<'T>通过使用StructuralComparison属性自动执行此操作。但是这种自动实现如何?

我可以使用哪种最简洁的替代方法来获取两个列表中最长的一个?

5 个答案:

答案 0 :(得分:6)

F#逐个元素地比较列表。如'B' > 'A'所以它考虑第一个列表&gt;第二(词典顺序)并打破进一步的比较。您可以使用列表中的.Length属性来比较长度。 像这样的例子;

let longest = if xs.Length > ys.Length then xs else ys

结果:

val longest : char list = ['A'; 'B'] 

答案 1 :(得分:1)

这是一个可重复使用的函数,用于检查任何2个序列的更长的长度:

let longest x y = match (Seq.length x > Seq.length y) with
                  |true -> x
                  |false -> y

答案 2 :(得分:1)

如果您想要通过某种属性比较两个对象的一般方法,可以创建maxBy函数:

let maxBy f x y = Array.maxBy f [|x; y|]

然后你可以这样做:

let longest = maxBy List.length xs ys

或直接:

let longest = Array.maxBy List.length [|xs; ys|]

答案 3 :(得分:1)

您可以编写maxBy函数:

let maxBy f a b = if f b > f a then b else a

然后这样称呼它:

let longestList = maxBy List.length xs ys

由于List.length是O(N),如果列表很长,性能将受到影响。操作将是O(N1 + N2),其中N1和N2是列表的长度。

如果一个很长而另一个很短,性能会不必要地受到影响。为避免这种情况,您可以编写更具体的功能。该函数为O(min(N1,N2)):

let getLongest list1 list2 =
    let rec helper = function
    | [], _ -> list2
    | _, [] -> list1
    | _ :: t1, _ :: t2 -> helper (t1, t2)
    helper (list1, list2)

let longestList = getLongest xs ys

答案 4 :(得分:0)

这是一个可重复使用的功能,可以从列表中返回最长的列表:

let longest ll = ll |> List.sortBy List.length |> List.rev |> List.head

示例:

> longest [xs; ys];;
val it : char list = ['A'; 'B']
> let zs = ['A' .. 'D'];;
val zs : char list = ['A'; 'B'; 'C'; 'D']
> longest [xs; zs; ys];;
val it : char list = ['A'; 'B'; 'C'; 'D']

但是,如果输入空列表,它就不起作用,因为在这种情况下你确实要确定你想要的行为。