Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/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
List F-如何将一个整数划分为(基本相等的)比这个更好的“桶”?_List_F#_Integer_Divide - Fatal编程技术网

List F-如何将一个整数划分为(基本相等的)比这个更好的“桶”?

List F-如何将一个整数划分为(基本相等的)比这个更好的“桶”?,list,f#,integer,divide,List,F#,Integer,Divide,我有一个整数,我想把它分成一个整数“bucket”列表,大小尽可能相等。 一些例子: 将10除以2会得到一个列表,即“[5;5]”5+5=10,或者, 将20除以3会得到一个列表,即“[7;7;6]”7+7+6=20,或者, 把15除以4,我就可以得到一个列表“[4;4;4;3]”4+4+4+3,诸如此类的东西。 较大的存储桶位于两端、中间或混合在一起并不重要,而是将一个进程划分为并行处理,顺序无关 我已经编写了一些代码,这些代码似乎工作正常,但似乎太混乱,难以推理: let integerBu

我有一个整数,我想把它分成一个整数“bucket”列表,大小尽可能相等。 一些例子:

将10除以2会得到一个列表,即“[5;5]”5+5=10,或者, 将20除以3会得到一个列表,即“[7;7;6]”7+7+6=20,或者, 把15除以4,我就可以得到一个列表“[4;4;4;3]”4+4+4+3,诸如此类的东西。 较大的存储桶位于两端、中间或混合在一起并不重要,而是将一个进程划分为并行处理,顺序无关

我已经编写了一些代码,这些代码似乎工作正常,但似乎太混乱,难以推理:

let integerBuckets total divider =
    match total, divider with
    | 0, _  -> [ 0 ]
    | 1, _ -> [ 1 ]
    | _, 0 -> [ total ] // Should  never happen, but checked just in case.
    | _, 1 -> [ total ]
    | _ ->
        let result = (double total) / (double divider)
        let remainder = total % divider
        [ for _ in 0 .. (remainder - 1) -> int (ceil result) ]
            @ [ for _ in 0 .. (divider - remainder - 1) -> int (floor result) ]

integerBuckets 15 4
我真的不喜欢循环中的数学;很容易犯错误和/或意外更改。但我不确定的不仅仅是数学方面

有谁能给我一些建议,告诉我如何“整理”成更好的F,这样更容易阅读


我并不是要求别人提供更好的代码片段,而是要求别人为我自己学习改进代码时应该关注的领域提供指导。

我认为下面的方法可行。基本上,我生成一个商列表,然后沿着列表分配剩余的1个单位,直到它被完全消耗

let integerBuckets total divider =
    let rem = total % divider
    let quo = total / divider
    let dividerList = [1..divider]
    [ for _ in dividerList do yield quo ]  //create list of quotients
    |> List.map2 (+) [for i in dividerList do if i <= rem then 1 else 0] //distribute remainder
编辑:

上述功能可概括如下:

let integerBuckets2 total divider =
    let rem,quo = total % divider,total / divider
    [ for i in [1..divider] do yield if i <= rem then quo + 1 else quo ]

我认为下面的方法会奏效。基本上,我生成一个商列表,然后沿着列表分配剩余的1个单位,直到它被完全消耗

let integerBuckets total divider =
    let rem = total % divider
    let quo = total / divider
    let dividerList = [1..divider]
    [ for _ in dividerList do yield quo ]  //create list of quotients
    |> List.map2 (+) [for i in dividerList do if i <= rem then 1 else 0] //distribute remainder
编辑:

上述功能可概括如下:

let integerBuckets2 total divider =
    let rem,quo = total % divider,total / divider
    [ for i in [1..divider] do yield if i <= rem then quo + 1 else quo ]

我建议您采取一种更面向数据的方法来解决这个问题,将作业拆分以进行处理。如果将要处理的项存储在数组中,则可以使用数组函数对其进行操作。以下是一些可能的方法:

let chunkByChunkCount array chunkCount =
    let chunkSize = 
        (float (Array.length array) / float chunkCount)
        |> ceil
        |> int
    array |> Array.chunkBySize chunkSize

chunkByChunkCount [| 1 .. 15 |] 4
// [|[|1; 2; 3; 4|]; [|5; 6; 7; 8|]; [|9; 10; 11; 12|]; [|13; 14; 15|]|]



let dealIntoChunks array chunkCount =
    array
    |> Array.indexed
    |> Array.groupBy (fun (i, _) -> i % chunkCount)
    |> Array.map snd
    |> Array.map (Array.map snd)

dealIntoChunks [| 1 .. 15 |] 4
// [|[|1; 5; 9; 13|]; [|2; 6; 10; 14|]; [|3; 7; 11; 15|]; [|4; 8; 12|]|]

我建议您采取一种更面向数据的方法来解决这个问题,将作业拆分以进行处理。如果将要处理的项存储在数组中,则可以使用数组函数对其进行操作。以下是一些可能的方法:

let chunkByChunkCount array chunkCount =
    let chunkSize = 
        (float (Array.length array) / float chunkCount)
        |> ceil
        |> int
    array |> Array.chunkBySize chunkSize

chunkByChunkCount [| 1 .. 15 |] 4
// [|[|1; 2; 3; 4|]; [|5; 6; 7; 8|]; [|9; 10; 11; 12|]; [|13; 14; 15|]|]



let dealIntoChunks array chunkCount =
    array
    |> Array.indexed
    |> Array.groupBy (fun (i, _) -> i % chunkCount)
    |> Array.map snd
    |> Array.map (Array.map snd)

dealIntoChunks [| 1 .. 15 |] 4
// [|[|1; 5; 9; 13|]; [|2; 6; 10; 14|]; [|3; 7; 11; 15|]; [|4; 8; 12|]|]

我不确定你在第二部分想做什么,但是你可以在同一个表达式中匹配total和divider,匹配total,divider with | 0,0->,这会缩短它一点谢谢你提到@onemorecupofcoffee。按照您的建议进行重构,我发现了逻辑中的一个严重缺陷,我希望已经纠正了。我已经根据需要更新了上面的代码。代码的其余部分是计算“bucket”的部分,这是我希望得到建议的主要部分。不确定在第二部分中您想做什么,但您可以在同一表达式中匹配total和divider,匹配total,divider with | 0,0->,这将缩短它一点感谢您提到@onemorecupofcoffee。按照您的建议进行重构,我发现了逻辑中的一个严重缺陷,我希望已经纠正了。我已经根据需要更新了上面的代码。代码的其余部分是计算“桶”的部分,这是我希望得到建议的主要内容。谢谢。有一些代码在那里,我还没有见过,但我仍然是一个非常初学者,所以我需要时间来理解它,但它看起来比我原来的好得多。乍一看,我认为我最喜欢第二段代码的外观,但我需要理解这两个方面。再次感谢。这两种方法都比我最初使用的方法要好得多,现在我了解了它们正在做什么,它们都更容易阅读。第一个版本,即使用map2的版本,执行时间大约是第二个版本的两倍-在五次单独运行中重复1000000次的平均时间,约为1.1秒,而不是0.6秒-因此我认为第二个版本的时间敏感代码应该使用第二个版本。不管怎样,代码都不错。再次感谢,谢谢你。有一些代码在那里,我还没有见过,但我仍然是一个非常初学者,所以我需要时间来理解它,但它看起来比我原来的好得多。乍一看,我认为我最喜欢第二段代码的外观,但我需要理解这两个方面。再次感谢。这两种方法都比我最初使用的方法要好得多,现在我了解了它们正在做什么,它们都更容易阅读。第一个版本,即使用map2的版本,执行时间大约是第二个版本的两倍-在五次单独运行中重复1000000次的平均时间,约为1.1秒,而不是0.6秒-因此我认为第二个版本的时间敏感代码应该使用第二个版本。不管怎样,代码都不错。再次感谢,谢谢你。和前面的答案一样,在更大的程度上,我有很多东西需要理解。我不完全确定我将如何进行处理,但我认为你的答案可能更接近t
o我最终需要的。整个过程将相当复杂,至少对初学者来说是这样,所以我现在正在尝试“小步骤”。再次感谢你给了我另一种看待这个问题的方式,非常感谢。和前面的答案一样,在更大的程度上,我有很多东西需要理解。我不完全确定我将如何进行处理,但我认为你的答案可能更接近我最终需要的。整个过程将相当复杂,至少对初学者来说是这样,所以我现在正在尝试“小步骤”。再次感谢你给了我另一种看待这个问题的方式,非常感谢。