List F#-生成列表的随机子集,其中包含单个和对的和

List F#-生成列表的随机子集,其中包含单个和对的和,list,random,f#,subset,List,Random,F#,Subset,我想生成一个输出列表,它是大小计数原始输入列表的随机生成子集,并分别对输出列表中的单个和对进行求和,我在下面的代码中显示了三个示例输出列表及其关联的单个和对求和: let input = [1; 1; 2; 2; 3; 3; 4; 4; 5; 5; 6; 6; 7; 7; 8; 9; 10; 11] let count = 11 let random = System.Random() let output = List.map (fun x -> input.[random.N

我想生成一个输出列表,它是大小计数原始输入列表的随机生成子集,并分别对输出列表中的单个和对进行求和,我在下面的代码中显示了三个示例输出列表及其关联的单个和对求和:

let input = [1; 1; 2; 2; 3; 3; 4; 4; 5; 5; 6; 6; 7; 7; 8; 9; 10; 11]
let count = 11
let random = System.Random()
let output = 
    List.map (fun x -> input.[random.Next(input.Length)]) 
    input
    |> Seq.take(count)
    |> Seq.toList

printfn "%A" output

// Output: [1; 1; 2; 2; 3; 3; 4; 4; 5; 5; 6]

// Sample 1: [1; 1; 2; 2; 3; 3; 4; 5; 8; 9; 11]
// Singles: 5 Pairs: 3
// Sample 2: [1; 2; 2; 3; 4; 5; 5; 6; 6; 7; 7]
// Singles: 3 Pairs: 4
// Sample 3: [1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11]
// Singles: 11 Pairs: 0

您的代码中有一个错误,
输入
应该与您的
地图
位于同一行,或者通过管道输入。否则,您可以通过以下功能实现所需:

let output = 
    input 
    |> List.map (fun x -> input.[random.Next(input.Length)])  
    |> Seq.take(count)
    |> Seq.countBy id |> Seq.groupBy snd |> Seq.map (snd >> Seq.length)
    |> Seq.toList
显然,你不能保证你只会得到单打或双人

添加1

你的随机函数不会做你认为它会做的事。它从原始列表中随机选择元素,但是您不能保证随机数生成器不会连续三次为您提供相同的数字。因此,您可以在列表中找到
[10,10,10]
。因此,对于第二条评论,如果您只是想洗牌列表,请使用
SortBy
。对于您的第一条评论,我刚刚定义了一个记录,它保存了无序列表和计数。您需要添加更多的错误处理逻辑,因为根据计数的不同,可能会得到一个只有单或对的列表。我还将
output
转换为一个函数,该函数包含两个参数:输入列表和计数。它更惯用,更容易使用

type ShuffledList = {
    counts : int list
    original : int list
}

let output input count = 
    let original = 
        input 
        |> List.sortBy (fun _ -> random.Next()) 
        |> Seq.take(count) |> Seq.toList
    let counts = 
        original
        |> Seq.countBy id |> Seq.groupBy snd |> Seq.map (snd >> Seq.length)
        |> Seq.toList
    {counts = counts ; original = original}

output input count

我想你可能想看看
seq.groupBy
——但你到底坚持哪一部分?我似乎在每次迭代中只生成[1;1;2;2;3;3;4;4;5;5;6]。你似乎想要的是计数而不是总和。为什么只有单打和双人?例如,您可以得到1。如何生成新列表和计数?请注意,从输入列表中,[1;1;2;2;3;3;4;4;5;5;6;6;7;7;8;9;10;11],1,2,3,4,5,6,7可以显示为单数或对数,但8,9,10,11只能显示为单数。三倍或以上是不允许的。@matekus请看我对答案的补充,特别是关于洗牌和随机抽样替换的部分。您也可以使用一些库函数从MathNet.Numerics执行此操作。代码中的一个细微更改——“let counts=input”应该是“let counts=original”…在计数中,有时单数和对数的顺序是相反的?