我需要一个快速的算法从一个通用列表中选择5个随机元素。例如,我想从一个List<string>
中获取5个随机元素。
我需要一个快速的算法从一个通用列表中选择5个随机元素。例如,我想从一个List<string>
中获取5个随机元素。
Dim ar As New ArrayList
Dim numToGet As Integer = 5
'hard code just to test
ar.Add("12")
ar.Add("11")
ar.Add("10")
ar.Add("15")
ar.Add("16")
ar.Add("17")
Dim randomListOfProductIds As New ArrayList
Dim toAdd As String = ""
For i = 0 To numToGet - 1
toAdd = ar(CInt((ar.Count - 1) * Rnd()))
randomListOfProductIds.Add(toAdd)
'remove from id list
ar.Remove(toAdd)
Next
'sorry i'm lazy and have to write vb at work :( and didn't feel like converting to c#
public static IEnumerable<T> TakeRandom<T>(this IEnumerable<T> elements, int countToTake)
{
var random = new Random();
var internalList = elements.ToList();
var selected = new List<T>();
for (var i = 0; i < countToTake; ++i)
{
var next = random.Next(0, internalList.Count - selected.Count);
selected.Add(internalList[next]);
internalList[next] = internalList[internalList.Count - selected.Count];
}
return selected;
}
http://arxiv.org/abs/1512.00501
def random_selection_indices(num_samples, N):
modified_entries = {}
seq = []
for n in xrange(num_samples):
i = N - n - 1
j = random.randrange(i)
# swap a[j] and a[i]
a_j = modified_entries[j] if j in modified_entries else j
a_i = modified_entries[i] if i in modified_entries else i
if a_i != j:
modified_entries[j] = a_i
elif j in modified_entries: # no need to store the modified value if it is the same as index
modified_entries.pop(j)
if a_j != i:
modified_entries[i] = a_j
elif i in modified_entries: # no need to store the modified value if it is the same as index
modified_entries.pop(i)
seq.append(a_j)
return seq
public static IEnumerable<Element> GetRandomElements(this IList<Element> list, int n)
{
var count = list.Count();
if (count < n)
{
throw new Exception("n cannot be bigger than the list size.");
}
var indexes = new HashSet<int>();
while (set.Count < n)
{
indexes.Add(Random.Next(count));
}
return indexes.Select(x => list[x]);
}
我使用这个作为参考:数组与列表的性能比较
实现还可以,因为列表足够快以通过id获取元素。
"随机"在方法范围之外定义,Hashset确保每个索引的唯一性。
限制:如果列表很大而n很小,则算法效果更好。否则,由于冲突,while循环可能需要很长时间。
在这种情况下使用
public static IEnumerable<Element> GetRandomElements(this IList<Element> list, int n)
{
return list.OrderBy(x => Random.Next()).Take(n);
}
可能是一个可用的选项
这将解决您的问题
var entries=new List<T>();
var selectedItems = new List<T>();
for (var i = 0; i !=10; i++)
{
var rdm = new Random().Next(entries.Count);
while (selectedItems.Contains(entries[rdm]))
rdm = new Random().Next(entries.Count);
selectedItems.Add(entries[rdm]);
}
C#
中的List<string>
,用户特别想要一个快速简单的解决方案。(显然,答案是排序并取五个。如果您在领域内做任何其他事情,那将是极其糟糕的工程。请注意,当然可以编造... - Fattie