在列表列表中对索引进行排序 - F#
Sorting indexes in list of lists - F#
目前我有一个函数return每个列表的第一个元素(浮点数),从一个列表到一个单独的列表。
let firstElements list =
match list with
| head::_ -> head
| [] -> 0.00
我的问题是,当我不知道这个列表有多长时,如何将它扩展到不同列表中同一索引处的 return 个元素?例如
let biglist = [[1;2;3];[4;5;6];[7;8;9]]
如果我不知道这个列表的长度,最有效和最安全的方法是什么
[[1;4;7];[2;5;8];[3;6;9]]
List.transpose
最近已添加到 FSharp.Core
let biglist = [[1;2;3];[4;5;6];[7;8;9]]
let res = biglist |> List.transpose
//val res : int list list = [[1; 4; 7]; [2; 5; 8]; [3; 6; 9]]
您可以使用最近添加的List.transpose
功能。但是自己足够好来创建这样的功能总是好的。如果你想自己解决问题,想一个通用的算法来解决你的问题。一个是。
- 从每个列表的第一个元素创建一个新列表
- 您删除每个列表的第一个元素
- 如果以空列表结束则结束,否则重复步骤 1)
这可能是解决问题的第一次尝试。函数名到此为止。
let transpose lst =
if allEmpty lst
then // Some Default value, we don't know yet
else ...
else
分支如下所示。首先,我们要选择每个元素的第一个元素。我们想象一个函数 pickFirsts
来完成这个任务。所以我们可以写 pickFirsts lst
。结果是一个列表,它本身是新列表的第一个元素。
新列表是剩余列表的结果。首先,我们再次想象一个函数,它删除每个 sub-list dropFirsts lst
的第一个元素。在该列表上,我们需要重复步骤 1)。我们通过递归调用 transpose
来做到这一点。
总的来说,我们得到:
let rec transpose lst =
if allEmpty lst
then // Some Default value, we don't know yet
else (pickFirsts lst) :: (transpose (dropFirsts lst))
此时我们可以想到默认值。 transpose
需要 return 一个值,以防它以空列表的空列表结尾。当我们使用 transpose
的结果向其添加一个元素时。它的结果必须是 list
。最好的默认值是一个空列表。所以我们最终得到了。
let rec transpose lst =
if allEmpty lst
then []
else (pickFirsts lst) :: (transpose (dropFirsts lst))
接下来我们需要实现剩余的函数allEmpty
、pickFirsts
和dropFirsts
。
pickFirst
很简单。我们需要遍历每个元素,并且必须 return 第一个值。我们通过 List.head
获得列表的第一个值,然后迭代它并将每个元素变成一个新列表就是 List.map
所做的。
let pickFirsts lst = List.map List.head lst
dropFirsts
需要遍历每个元素,只删除第一个元素,或者换句话说保留列表的remaining/tail。
let dropFirsts lst = List.map List.tail lst
剩下的 allEmpty
是一个谓词 return true/false 如果我们有一个空的列表列表。对于 return 值为 bool
的情况,我们需要另一个允许 return 另一种类型是列表的函数。这通常是使用 List.fold
的原因。实现可能如下所示:
let allEmpty lst =
let folder acc x =
match x with
| [] -> acc
| _ -> false
List.fold folder true lst
默认以true
开头。只要它找到空列表,它 return 的默认值就不会改变。一旦找到一个元素,在任何列表中,它将 return false
(非空)作为新的默认值。
全部代码:
let allEmpty lst =
let folder acc x =
match x with
| [] -> acc
| _ -> false
List.fold folder true lst
let pickFirsts lst = List.map List.head lst
let dropFirsts lst = List.map List.tail lst
let rec transpose lst =
if allEmpty lst
then []
else (pickFirsts lst) :: (transpose (dropFirsts lst))
transpose [[1;2;3];[4;5;6];[7;8;9]]
另一种方法是将其转换为二维可变数组。也做长度检查。进行转换并再次 return 可变数组作为不可变列表。
目前我有一个函数return每个列表的第一个元素(浮点数),从一个列表到一个单独的列表。
let firstElements list =
match list with
| head::_ -> head
| [] -> 0.00
我的问题是,当我不知道这个列表有多长时,如何将它扩展到不同列表中同一索引处的 return 个元素?例如
let biglist = [[1;2;3];[4;5;6];[7;8;9]]
如果我不知道这个列表的长度,最有效和最安全的方法是什么
[[1;4;7];[2;5;8];[3;6;9]]
List.transpose
最近已添加到 FSharp.Core
let biglist = [[1;2;3];[4;5;6];[7;8;9]]
let res = biglist |> List.transpose
//val res : int list list = [[1; 4; 7]; [2; 5; 8]; [3; 6; 9]]
您可以使用最近添加的List.transpose
功能。但是自己足够好来创建这样的功能总是好的。如果你想自己解决问题,想一个通用的算法来解决你的问题。一个是。
- 从每个列表的第一个元素创建一个新列表
- 您删除每个列表的第一个元素
- 如果以空列表结束则结束,否则重复步骤 1)
这可能是解决问题的第一次尝试。函数名到此为止。
let transpose lst =
if allEmpty lst
then // Some Default value, we don't know yet
else ...
else
分支如下所示。首先,我们要选择每个元素的第一个元素。我们想象一个函数 pickFirsts
来完成这个任务。所以我们可以写 pickFirsts lst
。结果是一个列表,它本身是新列表的第一个元素。
新列表是剩余列表的结果。首先,我们再次想象一个函数,它删除每个 sub-list dropFirsts lst
的第一个元素。在该列表上,我们需要重复步骤 1)。我们通过递归调用 transpose
来做到这一点。
总的来说,我们得到:
let rec transpose lst =
if allEmpty lst
then // Some Default value, we don't know yet
else (pickFirsts lst) :: (transpose (dropFirsts lst))
此时我们可以想到默认值。 transpose
需要 return 一个值,以防它以空列表的空列表结尾。当我们使用 transpose
的结果向其添加一个元素时。它的结果必须是 list
。最好的默认值是一个空列表。所以我们最终得到了。
let rec transpose lst =
if allEmpty lst
then []
else (pickFirsts lst) :: (transpose (dropFirsts lst))
接下来我们需要实现剩余的函数allEmpty
、pickFirsts
和dropFirsts
。
pickFirst
很简单。我们需要遍历每个元素,并且必须 return 第一个值。我们通过 List.head
获得列表的第一个值,然后迭代它并将每个元素变成一个新列表就是 List.map
所做的。
let pickFirsts lst = List.map List.head lst
dropFirsts
需要遍历每个元素,只删除第一个元素,或者换句话说保留列表的remaining/tail。
let dropFirsts lst = List.map List.tail lst
剩下的 allEmpty
是一个谓词 return true/false 如果我们有一个空的列表列表。对于 return 值为 bool
的情况,我们需要另一个允许 return 另一种类型是列表的函数。这通常是使用 List.fold
的原因。实现可能如下所示:
let allEmpty lst =
let folder acc x =
match x with
| [] -> acc
| _ -> false
List.fold folder true lst
默认以true
开头。只要它找到空列表,它 return 的默认值就不会改变。一旦找到一个元素,在任何列表中,它将 return false
(非空)作为新的默认值。
全部代码:
let allEmpty lst =
let folder acc x =
match x with
| [] -> acc
| _ -> false
List.fold folder true lst
let pickFirsts lst = List.map List.head lst
let dropFirsts lst = List.map List.tail lst
let rec transpose lst =
if allEmpty lst
then []
else (pickFirsts lst) :: (transpose (dropFirsts lst))
transpose [[1;2;3];[4;5;6];[7;8;9]]
另一种方法是将其转换为二维可变数组。也做长度检查。进行转换并再次 return 可变数组作为不可变列表。