F#添加到列表没有发生

时间:2014-10-05 01:56:24

标签: f#

嘿伙计们,我的F#计划遇到了一些麻烦。我基本上有一个未知数量的大小12浮动列表(通过读取文件和解析处理),我想采取这些列表并将它们分成12个列表,分别对应每个元素。因此,例如,我希望列表中的所有第5个元素都进入n5,依此类推。我的列表声明在我的代码顶部

let (n1: float list) = []
let (n2: float list) = []
let (n3: float list) = []
let (n4: float list) = []
let (n5: float list) = []
let (n6: float list) = []
let (n7: float list) = []
let (n8: float list) = []
let (n9: float list) = []
let (n10: float list) = []
let (n11: float list) = []
let (n12: float list) = []

递归访问器

let rec accsessline line = 
  if line = [] then
    ()  
   else      
     let (year, values) = ParseLine line.Head   
     (Pusher values)
     accsessline line.Tail

一个列表填充方法,在上面的代码段中调用(注意我的注释)

let Pusher (yearsFalls : float list)  =
    printfn "years falls are %f" yearsFalls.[6] //this line correctly accesses and prints the right element (6th) in each list yearsFalls.
    yearsFalls.[0] :: n1
    yearsFalls.[1] :: n2
    yearsFalls.[2] :: n3
    yearsFalls.[3] :: n4
    yearsFalls.[4] :: n5
    yearsFalls.[5] :: n6
    yearsFalls.[6] :: n7
    yearsFalls.[7] :: n8
    yearsFalls.[8] :: n9
    yearsFalls.[9] :: n10
    yearsFalls.[10] :: n11
    yearsFalls.[11] :: n12

现在一切正常,它只是我试图添加到这些无法正常工作的列表的部分。当我在调用上述访问线函数后打印出n1-n12列表中的一个时,正确的元素是我的输出中显示的printfn,它打印出每行的第6个元素(我的代码中唯一的注释),但是列表打印为空括号" []"。它只是对n1-n12列表的实际添加没有发生。您是否知道我需要做些什么才能使实施工作?谢谢你的时间!

2 个答案:

答案 0 :(得分:2)

您应该意识到F# list是一个不可变的数据结构,就像下面的FSI简单实验所示:

> let ll: int list = [];;
val ll : int list = []
> 1::ll;;
val it : int list = [1] // expression value is a new list
> ll;;
val it : int list = []  // ...but original list did not change ?!

为了在列表中累积元素,F#中至少存在两种​​方式:

  • 强制列表可变的非惯用的:

> let mutable ll: int list = [];;
val mutable ll : int list = []
> ll <- 1 :: ll;; // mutate list by prepending an element
val it : unit = ()
> ll;;
val it : int list = [1] // list has changed
  • 组合功能应用程序的惯用之一:

> let prepend l ll = l :: ll;;
val prepend : l:'a -> ll:'a list -> 'a list
> [] |> prepend 1;;
val it : int list = [1]
> [] |> prepend 1 |> prepend 2;;
val it : int list = [2; 1]
........................

这也许给了足够的线索来非惯用地实现你的程序。对于惯用解决方案,考虑到以下更简单的解决方案,但类似的问题可能有所帮助:想象你需要分区整数列表,将奇数元素放入一个列表,偶数元素放入另一个列表。以下代码段将执行:

>let rec partition (odds,evens) ll =
    match ll with
    | [] -> (odds,evens)
    | h::t -> match h % 2 with
              | 0 -> partition (odds, h :: evens) t
              | _ -> partition (h :: odds, evens) t;;

val partition :
  odds:int list * evens:int list -> ll:int list -> int list * int list

> partition ([],[]) [1;42;-3;7;14];;
val it : int list * int list = ([7; -3; 1], [14; 42])

了解上述工作原理,并对原始问题采用类似的方法。祝你好运!

答案 1 :(得分:0)

正如Gene指出的那样,您正在使用不可变数据结构,因此您的n1..n12列表在引用时将始终为空。相反,您需要累积列表,然后返回一个列表,然后您可以存储这些列表。或者,当声明每个n1..n12列表时,您可以在声明它们时找到每个列表的元素。

我用你建议的方式分发假定未知数量的长度为12的整数列表的元素:

// Some list to work on as input, read from your file for instance
let list = 
    [
        [1..12] 
        [1..12]
        [1..12]
        [1..12]
        [1..12]
        [1..12]
        [1..12]
        [1..12]
        [1..12]
    ]
let distributeElements inputList =
    // For each sublist of the inputList take out the appropriate element and add it to the list, then move on to the next sublist
    let rec gatherFromEachSubList (inputList: list<list<int>>) indexOfInput elementNumber accum =
        if indexOfInput < (inputList |> List.length) then 
            let newAccum = inputList.[indexOfInput].[elementNumber - 1] :: accum
            gatherFromEachSubList inputList (indexOfInput+1) elementNumber newAccum
        else 
            accum

    // For each category (n1..n12) gather from the sublists of the inputlist
    let rec gatherLists inputList elementNumber accum =
        if elementNumber > 0 then
            let newAccum = gatherFromEachSubList inputList 0 elementNumber List.empty :: accum
            gatherLists inputList (elementNumber - 1) newAccum
        else
            accum
    gatherLists inputList 12 List.empty

[<EntryPoint>]
let main argv =     
    let result = distributeElements list
    result |> List.map (fun a -> printfn "%A" a) |> ignore
    0 // return an integer exit code

在FSI中运行的结果:

let result = distributeElements list
result |> List.map (fun a -> printfn "%A" a) |> ignore;;

[1; 1; 1; 1; 1; 1; 1; 1; 1]
[2; 2; 2; 2; 2; 2; 2; 2; 2]
[3; 3; 3; 3; 3; 3; 3; 3; 3]
[4; 4; 4; 4; 4; 4; 4; 4; 4]
[5; 5; 5; 5; 5; 5; 5; 5; 5]
[6; 6; 6; 6; 6; 6; 6; 6; 6]
[7; 7; 7; 7; 7; 7; 7; 7; 7]
[8; 8; 8; 8; 8; 8; 8; 8; 8]
[9; 9; 9; 9; 9; 9; 9; 9; 9]
[10; 10; 10; 10; 10; 10; 10; 10; 10]
[11; 11; 11; 11; 11; 11; 11; 11; 11]
[12; 12; 12; 12; 12; 12; 12; 12; 12]