为什么 max (Operator) 不是 return 最长的列表?
Why does max (Operator) not return the longest list?
我想找出两个列表中最长的一个。考虑以下代码示例:
let xs = ['B']
let ys = ['A'; 'B']
let longest = max xs ys
printfn "%A" longest
与我的预期相反,该程序的输出是 ['B']
而不是 ['A'; 'B']
。
为什么List<'T>
implement max
会这样? How/where 这个实现到底有没有定义?
我可以看到 max
需要 comparison
,我认为这意味着 IComparable
的实现。 List<'T>
通过使用 StructuralComparison
属性自动执行此操作。但是这个自动实现是什么样子的呢?
要获得两个列表中最长的列表,最简洁的替代方法是什么?
F# 逐个元素地比较列表。作为 'B' > 'A'
所以它考虑第一个列表>第二个(字典顺序)并打破进一步的比较。您可以在列表中使用 .Length
属性 来比较长度。
例如这样;
let longest = if xs.Length > ys.Length then xs else ys
结果:
val longest : char list = ['A'; 'B']
这是一个可重复使用的函数,用于检查任意 2 个序列的较大长度:
let longest x y = match (Seq.length x > Seq.length y) with
|true -> x
|false -> y
如果你想要一个通用的方法来比较两个对象 属性 你可以创建一个 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|]
这是一个可重复使用的函数,它将 return 来自 列表的最长列表 :
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']
但是,如果您输入空列表,它将不起作用,因为在这种情况下,您需要准确定义您希望的行为。
你可以写一个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
我想找出两个列表中最长的一个。考虑以下代码示例:
let xs = ['B']
let ys = ['A'; 'B']
let longest = max xs ys
printfn "%A" longest
与我的预期相反,该程序的输出是 ['B']
而不是 ['A'; 'B']
。
为什么List<'T>
implement max
会这样? How/where 这个实现到底有没有定义?
我可以看到 max
需要 comparison
,我认为这意味着 IComparable
的实现。 List<'T>
通过使用 StructuralComparison
属性自动执行此操作。但是这个自动实现是什么样子的呢?
要获得两个列表中最长的列表,最简洁的替代方法是什么?
F# 逐个元素地比较列表。作为 'B' > 'A'
所以它考虑第一个列表>第二个(字典顺序)并打破进一步的比较。您可以在列表中使用 .Length
属性 来比较长度。
例如这样;
let longest = if xs.Length > ys.Length then xs else ys
结果:
val longest : char list = ['A'; 'B']
这是一个可重复使用的函数,用于检查任意 2 个序列的较大长度:
let longest x y = match (Seq.length x > Seq.length y) with
|true -> x
|false -> y
如果你想要一个通用的方法来比较两个对象 属性 你可以创建一个 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|]
这是一个可重复使用的函数,它将 return 来自 列表的最长列表 :
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']
但是,如果您输入空列表,它将不起作用,因为在这种情况下,您需要准确定义您希望的行为。
你可以写一个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