在列表列表中排序索引-F#
目前,我有一个函数可以将列表中每个列表的第一个元素(浮动)返回到一个单独的列表中在列表列表中排序索引-F#,f#,iteration,sublist,F#,Iteration,Sublist,目前,我有一个函数可以将列表中每个列表的第一个元素(浮动)返回到一个单独的列表中 let firstElements list = match list with | head::_ -> head | [] -> 0.00 我的问题是,当我不知道这个列表有多长时,如何扩展它以将相同索引中的元素返回到不同的列表中?比如说 let biglist = [[1;2;3];[4;5;6];[7;8;9]] 如果我不知道这个列表的长度,那么最有效、最安全的方法是什
let firstElements list =
match list with
| head::_ -> head
| [] -> 0.00
我的问题是,当我不知道这个列表有多长时,如何扩展它以将相同索引中的元素返回到不同的列表中?比如说
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
功能。但是,自己创建这样的函数总是很好的。如果你想自己解决问题,想一个通用的算法来解决你的问题。一个是
let transpose lst =
if allEmpty lst
then // Some Default value, we don't know yet
else ...
else
分支如下所示。首先,我们要选择每个元素的第一个元素。我们设想一个函数pickFirsts
来完成这个任务。所以我们可以编写pickFirsts lst
。结果是一个列表,它本身是新列表的第一个元素
新列表是剩余列表的结果。首先,我们再次设想一个函数,它删除每个子列表的第一个元素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))
此时,我们可以考虑默认值<代码>转置需要返回一个值,以防它以空列表的空列表结束。因为我们使用转置的结果
向其添加元素。它的结果必须是一个列表
。最好的默认值是一个空列表。因此,我们最终得到了
let rec transpose lst =
if allEmpty lst
then []
else (pickFirsts lst) :: (transpose (dropFirsts lst))
接下来,我们需要实现剩余的函数allEmpty
,pickFirsts
和dropFirsts
pickFirst
很容易。我们需要迭代每个元素,并且必须返回第一个值。我们通过list.head
获得列表的第一个值,并对其进行迭代,将每个元素转换为一个新的列表,这就是list.map
所做的
let pickFirsts lst = List.map List.head lst
dropFirsts
需要迭代每个元素,只需删除第一个元素,或者换句话说,保留列表的剩余/尾部
let dropFirsts lst = List.map List.tail lst
剩下的allEmpty
是一个谓词,如果列表列表是否为空,则返回true/false。返回值为bool
,我们需要另一个允许返回另一种类型的函数,即列表。这通常是使用List.fold
的原因。实现可以如下所示:
let allEmpty lst =
let folder acc x =
match x with
| [] -> acc
| _ -> false
List.fold folder true lst
它以true
作为默认值开始。只要找到空列表,它就会返回默认值不变。一旦在任何列表中找到一个元素,它将返回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]]
另一种方法是将其转换为二维可变数组。也做长度检查。进行转换,然后将可变数组作为不可变列表再次返回。看起来像是一个分组方式。这看起来像是您实际要做的是转置矩阵;也许可以研究一下这方面的算法。(如果我理解正确,FSharp.Core将来将包含一个函数。)@TeaDrivenDev的可能副本它已经在那里了这是比我更好的答案。向我投最大的一票。我应该感到骄傲