Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F#:类似Clojure中的配分函数_Clojure_F# - Fatal编程技术网

F#:类似Clojure中的配分函数

F#:类似Clojure中的配分函数,clojure,f#,Clojure,F#,Clojure有一个很好的函数叫做partition,它可以处理序列。它将一个给定的序列分解为一个同样长的列表序列。第一个参数指定fragaments的长度。第二个参数是一个偏移量,用于指定片段的下一个起点 (partition 3 1 (range 5)) ;;=> ((0 1 2) (1 2 3) (2 3 4)) (partition 4 6 (range 20)) ;;=> ((0 1 2 3) (6 7 8 9) (12 13 14 15)) (partition 4

Clojure有一个很好的函数叫做partition,它可以处理序列。它将一个给定的序列分解为一个同样长的列表序列。第一个参数指定fragaments的长度。第二个参数是一个偏移量,用于指定片段的下一个起点

(partition 3 1 (range 5))
;;=> ((0 1 2) (1 2 3) (2 3 4))

(partition 4 6 (range 20))
;;=> ((0 1 2 3) (6 7 8 9) (12 13 14 15))

(partition 4 3 (range 20))
;;=> ((0 1 2 3) (3 4 5 6) (6 7 8 9) (9 10 11 12) (12 13 14 15) (15 16 17 18))

我在寻找F#中的一个等价函数。显然,List.partition还做了其他事情()。也许有一个图书馆提供这样的功能

在F#中有两个类似的函数:
windowed
,它类似于Clojure的分区,但第二个参数固定为1,第二个参数等于第一个参数

您可以将两者结合起来,获得所需的功能。下面是一个列表示例:

let partition x y = List.windowed x >> List.chunkBySize y >> List.map List.head
它们也可用于数组和序列,但请注意,对于序列,内部集合将是一个数组,实际上是一个序列。因此,如果您希望将结果严格推断为序列序列,则必须添加转换或向上转换:

let partition x y = Seq.windowed x >> Seq.chunkBySize y >> Seq.map (Seq.head >> seq)

你可以自己实现这个函数,正如@Gustavo所展示的,这并不难。一个问题是,您刚刚完成的功能是否正常工作

下面是一个用于测试配分函数属性的实现和属性测试

FsCheck
是检查刚刚实现的函数是否具有正确属性的好工具

open FsCheck

let partition (size : int) (increment : int) (vs : 'T []) : 'T [] [] =
  let size      = max 1 size
  let increment = max 1 increment
  let length    = vs.Length
  [| for i in [size..increment..length] -> vs.[(i - size)..(i - 1)] |]

let range (n : int) : int [] = [| 0..(n - 1) |] 

type Properties() =

  static member ``all partitions have the right size`` (size : int, increment : int, vs : int []) =
    (size > 1 && increment > 1 && vs.Length > 1) ==> 
      fun () ->
        let partitions = partition size increment vs
        // Iterates over partitions and make sure they have the same Length = size
        let rec check = function
          | i when i < 
            partitions.Length -> partitions.[i].Length = size && (check (i + 1))
          | _ -> true
        check 0

  static member ``all partitions have been incremented the right way`` (size : int, increment : int, vs : int []) =
    (size > 1 && increment > 1 && vs.Length > 1) ==>
      fun () ->
        let ivs = vs |> Array.mapi (fun i v -> (i,v))
        let partitions = partition size increment ivs
        // Iterates over partitions and make sure the first element has the right increment
        let rec check = function
          | i when i < partitions.Length -> 
            let ii, vv = partitions.[i].[0]
            ii = (i*increment) && vv = vs.[ii]  && (check (i + 1))
          | _ -> true
        check 0

  static member ``all partitions have the right content`` (size : int, increment : int, vs : int []) =
    (size > 1 && increment > 1 && vs.Length > 1) ==> 
      fun () ->
        let ivs = vs |> Array.mapi (fun i v -> (i,v))
        let partitions = partition size increment ivs
        // Iterates over partitions and make sure the each in the partition is correct element
        let rec check = function
          | i when i < partitions.Length -> 
            let partition = partitions.[i]
            let exp       = i*increment
            let rec check_partition = function
              |  i when i < partition.Length -> 
                let ii, vv = partition.[i] 
                ii = (exp + i) && vv = vs.[ii] && check_partition (i + 1)
              | _ -> true
            check_partition 0 && (check (i + 1))
          | _ -> true
        check 0

[<EntryPoint>]
let main argv = 
  range 5   |> partition 3 1 |> printfn "%A"
  range 20  |> partition 4 6 |> printfn "%A"
  range 20  |> partition 4 3 |> printfn "%A"

  let config = { Config.Quick with MaxFail = 100000; MaxTest = 1000 }

  // Generates random data and make sure the properties holds for any random data
  Check.All<Properties> config

  0
打开FsCheck
let分区(大小:int)(增量:int)(vs:'T[]):'T[]=
让大小=最大1个大小
设增量=最大1增量
让长度=vs.长度
[|对于[size..increment..length]中的i]->与[i-size..(i-1)]|]
let range(n:int):int[]=[|0..(n-1)|]
类型属性()=
静态成员``所有分区的大小``(大小:int,增量:int,vs:int[])=
(大小>1和增量>1和长度>1)=>
乐趣()->
let partitions=分区大小增量vs
//迭代分区并确保它们具有相同的长度=大小
let rec check=函数
|当我
partitions.Length->partitions[i].Length=size&&(检查(i+1))
|_uu->true
检查0
静态成员``所有分区都以正确的方式递增``(大小:int,递增:int,vs:int[])=
(大小>1和增量>1和长度>1)=>
乐趣()->
设ivs=vs |>Array.mapi(乐趣i v->(i,v))
let partitions=分区大小增量ivs
//迭代分区并确保第一个元素具有正确的增量
let rec check=函数
|当i
设ii,vv=分区[i].[0]
ii=(i*增量)和&vv=vs.[ii]&&(检查(i+1))
|_uu->true
检查0
静态成员``所有分区都有正确的内容``(大小:int,增量:int,vs:int[])=
(大小>1和增量>1和长度>1)=>
乐趣()->
设ivs=vs |>Array.mapi(乐趣i v->(i,v))
let partitions=分区大小增量ivs
//迭代分区并确保分区中的每个元素都是正确的元素
let rec check=函数
|当i
让partition=partitions[i]
设exp=i*增量
让rec检查分区=函数
|当i
设ii,vv=partition[i]
ii=(exp+i)和&vv=vs.[ii]&检查分区(i+1)
|_uu->true
检查分区0&(检查(i+1))
|_uu->true
检查0
[]
让主argv=
范围5 |>分区3 1 |>打印fn“%A”
范围20 |>分区4 6 |>打印fn“%A”
范围20 |>分区4 3 |>打印fn“%A”
让config={config.Quick with MaxFail=100000;MaxTest=1000}
//生成随机数据并确保属性适用于任何随机数据
检查所有配置
0
所以即使你没有要求这个,我想也许你对它感兴趣