我想找到两个列表中最长的一个。请考虑以下代码示例:
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
属性自动执行此操作。但是这种自动实现如何?
我可以使用哪种最简洁的替代方法来获取两个列表中最长的一个?
答案 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']
但是,如果输入空列表,它就不起作用,因为在这种情况下你确实要确定你想要的行为。