【问题标题】:Confused on accessing data in a list of tuples F#对访问元组列表中的数据感到困惑 F#
【发布时间】:2015-02-14 06:19:20
【问题描述】:
//Return a tuple from a text file:
let ExtractFromLine (line:string) =
 let strings = line.Split('\t') //data members are spaced by tab
 let strlist = Array.toList(strings) //each data member is now a list of str
 let year = System.Int32.Parse(strlist.Head) //year is first in file, so Head
 let values = List.map System.Double.Parse strlist.Tail //tail are all values
 let average = List.average values //not part of text file
 let min = List.min values //not part of text file
 let max = List.max values //not part of text file
 (year, values, average, min, max) //return tuple with all info

//----------
let rec createList fileline =
 if fileline = [] then
  []
 else 
  let (year, values, average, min, max) = ExtractFromLine fileline.Head
  let l = (year, values, average, min, max) :: createList fileline.Tail
  l

//------------
let main argv =
 let file = ReadFile "data.txt"

 let biglist = createList file //recursive function to make a list of tuples
 printfn"%A" biglist //This prints the year, all values, average, min, and max for each tuple created

我现在有一个巨大的元组列表,其中包含我需要的所有信息。 我是否保留了访问内部所有元素并对其执行计算的可能性?我使用 C++ 编程,并且该解决方案在该语言中是可行的,但在我看来 F# 要强大得多。我确信它是可能的,我只是缺少基础知识。

例如,如何打印所有年份的所有值的平均值? 我正在考虑一个 for 循环,但我不确定如何迭代。

for(all tuples in biglist)
printfn"%A:%A" tuple.year tuple.average

这显然是错误的,但我想你们明白我想要做什么。

上述问题涉及一次从列表中的一个元组中提取数据。 如果我想打印最大的平均值怎么办?这将涉及访问每个元组的平均数据成员并比较它们以返回最大的。我是否必须创建另一个包含这些平均值的列表?

我了解了 fst 和 snd,但我很难将其应用到这个示例中。 如果问题太多,您不必回答所有问题,但是当我开始使用这种语言时,非常感谢您提供任何帮助,谢谢

【问题讨论】:

    标签: f# tuples


    【解决方案1】:

    您可以在 F# 中循环,但它是来自命令式编程世界的构造。更惯用的方法是递归访问列表中的项目。

    下面是一些创建元组、构造列表、然后访问项目并检查哪个更大的示例代码。查看您的代码,平均值是元组中的第三项。这就是我添加trd 函数的原因。它需要一个 5 项元组并返回第三项。

    prcsLst 函数有 2 个参数:一个列表和一个起始最大值。这个想法是,在处理列表时,我们获取头部(列表中的第一项),将其平均值与当前最大值进行比较。较大者与列表的尾部(没有第一项的列表)一起传递到下一个递归轮。在这种情况下,作为初始最大值,我传入了第一项的平均值。

    您可以在 F# Interactive 中运行示例以查看结果。

    // create sample tuples
    let t1 = (2014, 35, 18, 5, 45)
    let t2 = (2014, 32, 28, 8, 75)
    let t3 = (2014, 25, 11, 9, 55)
    let t4 = (2015, 16, 13, 2, 15)
    let t5 = (2015, 29, 15, 1, 35)
    
    // create sample list
    let lst = [t1;t2;t3;t4;t5]
    
    // a function to return third item in a tuple
    let trd (_,_,t,_,_) = t
    
    // process list recursively
    let rec prcsLst l max =
        match l with
        | [] -> max
        | hd::tl ->
            if (trd hd) > max then
                prcsLst tl (trd hd)
            else
                prcsLst tl max
    
    
    // invoke the method on the sample list
    // as a starting point use the first item in the list
    prcsLst lst (trd t1);;
    

    【讨论】:

    • 这回答了我关于跨同一列表中的元组访问相似数据成员的问题。谢谢!
    • 或者,使用trd,您可以简单地执行List.maxBy trd lst(其优点是返回与最大值关联的整个元组)@filposs
    【解决方案2】:

    在手机上,请原谅我没有做任何代码示例:)

    我怀疑您的难题中缺少的部分称为模式匹配。在 F# 中,您可以像这样处理元组的元素:

    let (y, v, Av, mn, mx) = mytuple
    

    请注意,您也可以在函数声明中以及进行“匹配”时使用它。

    (“twoples”有一个例外,您可以使用函数“fst”和“snd”)

    您应该使用的另一件事是 |> 运算符。

    【讨论】:

    • 使用我上面的代码,我试图解决我的 touple 中的元素,如 let (year,values,average,min,max) = biglist ,但错误错误44 这个表达式应该有类型 'a * 'b * 'c * 'd * 'e 但这里有类型 (int * float list * float * float * float) list
    • 嗯,是的,我的例子是一个元组。如果您有它们的列表,您将需要使用像 map 或 average 这样的 List 函数,然后模式匹配将发生在您通过列表传入的函数中。 mylist |> List.map (fun (a, b, c, _, _) -> do whatever with a, b, c)
    • 太棒了,谢谢! List.map 就是我要找的东西! List.map 是否还允许跨元组数据访问,例如提取最大平均值?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-09
    相关资源
    最近更新 更多