我正在尝试为我正在处理的网站构建一个随机样本和随机分配生成器,该网站应该将相同数量的随机选择项分配给一组变量人。
例如:
在本轮评估中,我们有9名评估员,477项需要由两名评估员评分(同一评估员未对同一项目评分两次)。这将需要进行954次“评估”,每位评估员需要106次。
因此我需要一个像......这样的最终清单。
(Item, Assessor1, Assessor2)
(1, A, B)
(2, C, D)
(3, E, F)
(4, G, H)
(5, H, B)
(6, B, F)
.
.
.
And so on
我发现可以进行随机数生成的网站,甚至可以对群组进行随机分配的网站,但即便如此,我仍然会发现同一评估者将在整个结果中对同一项进行评分的情况。
我不太关心固有的随机性,更关心的是确保每个结果列表让每个评估者对相同数量的项目进行评分而不对同一项目进行评分。
我通常可以得到它 - 关闭 - 并且可能一个等级将是1或2个,而另一个将少1或2个,但不幸的是,它们是相同分组的硬性要求。 / p>
修改
实施@ Tinstaafl的代码并执行以下操作:
Dim col As New MyItemCollection
col.AddAssessor("A")
col.AddAssessor("B")
col.AddAssessor("C")
col.AddAssessor("D")
col.AddAssessor("E")
col.AddAssessor("F")
col.AddAssessor("G")
col.AddAssessor("H")
col.AddAssessor("I")
For I As Integer = 1 To 477
col.AddItem(I.ToString)
Next
Dim newList As List(Of MyItemCollection.MyItem) = col.AssignAssessors
For Each item As MyItemCollection.MyItem In col.itemlist
Response.Write(item.ToString & "<br/>")
Next
不幸的是我的输出看起来像
1 - F - F
2 - I - I
3 - E - E
4 - F - F
5 - C - C
6 - D - D
7 - G - G
8 - A - A
9 - C - C
10 - B - B
11 - D - D
12 - D - D
13 - D - D
14 - D - D
15 - H - H
等等......
答案 0 :(得分:0)
我能想到的一个想法如下:
对评估员进行洗牌{1-9}。然后根据此shuffle的结果顺序将前4.5个项目分配给它们。
然后再次洗牌。再次按顺序将它们分配给下一个项目。如果第一个评估者恰好是已经分配给第5个项目的评估者,那么在列表中交换第一个和第二个评估者。
继续为所有项目执行此操作。
答案 1 :(得分:0)
一种方法是使用集合类和项目和评估者的嵌入类。这是一个部分实现,用于说明如何生成列表:
Public Class MyItemCollection
Class Assessor
Public Name As String = ""
Public Shared Operator <>(LH As Assessor, RH As Assessor) As Boolean
Return LH.Name <> RH.Name
End Operator
Public Shared Operator =(LH As Assessor, RH As Assessor) As Boolean
Return RH.Name = LH.Name
End Operator
Public Overrides Function ToString() As String
Return Name
End Function
End Class
Class MyItem
Public Name As String = ""
Public Assessor1 As New Assessor
Public Assessor2 As New Assessor
Public Overrides Function ToString() As String
Return Name & " - " & Assessor1.ToString & " - " & Assessor2.ToString
End Function
End Class
Private AssessorList As New List(Of Assessor)
Private ItemList As New List(Of MyItem)
Public Sub AddAssessor(Name As String)
AssessorList.Add(New Assessor With {.Name = Name})
End Sub
Public Sub AddItem(Name As String)
ItemList.Add(New MyItem With {.Name = Name})
End Sub
Private Rnd As New Random(Now.Millisecond * Now.Day * Now.Minute)
Public Function AssignAssessors() As List(Of MyItem)
Dim OutVal As New List(Of MyItem)
Dim average As Integer = ((ItemList.Count \ AssessorList.Count) * 2) + 5
Dim AssessorCount(AssessorList.Count - 1) As Integer
For Each item As MyItem In ItemList
Dim firstassessorindex As Integer
Do
firstassessorindex = Rnd.Next(0, AssessorList.Count)
Loop Until AssessorCount(firstassessorindex) <= average
item.Assessor1 = AssessorList(firstassessorindex)
AssessorCount(firstassessorindex) += 1
Dim secondassessorindex As Integer
Do
secondassessorindex = Rnd.Next(0, AssessorList.Count)
Loop Until AssessorList(secondassessorindex) <> item.Assessor1 AndAlso AssessorCount(secondassessorindex) < average
item.Assessor2 = AssessorList(secondassessorindex)
AssessorCount(secondassessorindex) += 1
Next
OutVal = ItemList
Return OutVal
End Function
End Class
你的解释中有一点不清楚的是,Assessor1和Assessor2之间的分配是否重要(如果评估员是第二次评估员的次数比第一次评估者多吗?)。如果需要,那么AssessorCount可能需要List(Of Tuple(Integer,Integer))而不是List(Of Integer)
返回列表中每个项目的ToString
方法格式为 -
ItemName - Assessor1Name - Assessor2Name
答案 2 :(得分:0)
我不确定我是否理解你的作业规则,但这可能很接近。
var assessors = new []
{
"A", "B", "C",
"D", "E", "F",
"G", "H", "I",
};
var rnd = new Random();
var query =
from a1 in assessors
from a2 in assessors
where a1 != a2
orderby rnd.Next()
select new { a1, a2};
var results =
Enumerable
.Range(1, 477)
.Zip(query
.Repeat(),
(i, aa) => new
{
Item = i,
Assessor1 = aa.a1,
Assessor2 = aa.a2,
});
我得到了这样的结果:
1 F B
2 E C
3 D H
...
476 F C
477 B E