从列表F#中删除每个第3个元素

时间:2016-10-09 21:22:39

标签: list f#

我正在尝试在F#中编写一个模块,它将从列表中删除每个第3个元素,并返回一个没有这些元素的新列表。

例如

let  input = [ 1 .. 15 ] 

printfn "List with elements eliminated: %A" (Program1.remove input)

可以提供此输出

List with elements eliminated: [1; 2; 4; 5; 7; 8; 10; 11; 13; 14] 

到目前为止我尝试了什么

module Program1 =
 open System
 let remove list1=
    let collectList = List.iteri (fun i x -> if i%3 <> 0 then   x) list1
    collectList
[<EntryPoint>]
let main argv =
 let list = [ 1; 2; 3] 
 printfn "new List is %A" (Program1.remove list )
 0

现在我收到了一个错误,我整日都在尝试解决它。 提前谢谢

2 个答案:

答案 0 :(得分:1)

对于此错误:

 error FS0001: Type mismatch. Expecting a
    'unit list'
but given a
    'int list'
The type 'unit' does not match the type 'int'

问题来自第if i%3 <> 0 then x行。它是一个没有else子句的if-expression,它必须具有unit类型,类型推断导致x类型为unit。有关F#条件的更多详细信息,请阅读https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/conditional-expressions-if-then-else

编辑:此外,List.iteri没有执行您要执行的操作,因为List.iteri未返回列表,它返回unit。您需要List.mapList.filterList.chooseList.foldBack等功能来解决您的问题。

阅读此帖子中接受的答案,以了解如何解决此问题(您需要进行少量修改):Getting every nth Element of a Sequence

使用List.foldBack构建结果列表还有一种更简单的方法。

答案 1 :(得分:0)

我不确定您是否尝试过滤每个第三个值或每个可分为3的值。

如果它的第一种情况比一种功能性方法可能是这样的

//safe take and skip fn (no exceptions)
let take x xs = if List.length xs >= x then List.take x xs else [] 
let skip x xs = if List.length xs >= x then List.skip x xs else []
let rec remove x xs =
    //effectively this drops every xnt element
    let head = take (x - 1) xs
    let tail = skip x xs
    match tail with
    | [] -> head
    | _  -> List.append head (remove x tail)

let x = ["One";"Two";"Three";"Four";"Five";"Six";"Seven";"Eight";"Nine";"Ten"]
remove 3 x

然而,这是相当重的;-)
所以更好的方法可能就像你几乎找到的那样

let x = ["One";"Two";"Three";"Four";"Five";"Six";"Seven";"Eight";"Nine";"Ten"]
let indices = [1 .. List.length x]

List.zip indices x 
|> List.filter (fun (x,_) -> x % 3 <> 0)