我需要一个快速算法来从通用列表中选择4个随机元素。例如,我想从List中获取4个随机元素,然后根据一些计算,如果找到的元素无效,那么它应该再次从列表中选择接下来的4个随机元素。
答案 0 :(得分:1)
您可以将索引存储在某个列表中以获取非重复索引:
List<T> GetRandomElements<T>(List<T> allElements, int randomCount = 4)
{
if (allElements.Count < randomCount)
{
return allElements;
}
List<int> indexes = new List<int>();
// use HashSet if performance is very critical and you need a lot of indexes
//HashSet<int> indexes = new HashSet<int>();
List<T> elements = new List<T>();
Random random = new Random();
while (indexes.Count < randomCount)
{
int index = random.Next(allElements.Count);
if (!indexes.Contains(index))
{
indexes.Add(index);
elements.Add(allElements[index]);
}
}
return elements;
}
然后你可以做一些计算并调用这个方法:
void Main(String[] args)
{
do
{
List<int> elements = GetRandomelements(yourElements);
//do some calculations
} while (some condition); // while result is not right
}
答案 1 :(得分:1)
类似的东西:
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var list = new List<int>();
list.Add(1);
list.Add(2);
list.Add(3);
list.Add(4);
list.Add(5);
int n = 4;
var rand = new Random();
var randomObjects = new List<int>();
for (int i = 0; i<n; i++)
{
var index = rand.Next(list.Count);
randomObjects.Add(list[index]);
}
}
}
答案 2 :(得分:1)
你可以这样做
Test1
然后使用这样的扩展方法:
Test
答案 3 :(得分:0)
假设List的长度为N.现在假设您将这4个数字放在另一个被调用的List中。然后你可以循环遍历List,你选择的元素的概率是
angular.module('MyApp', ['ngMaterial'])
.controller('csrClrt', function ($scope) {
stylesdata = [{
name: "a",
id: 0
}, {
name: "b",
id: 1
}, {
name: "c",
id: 3
}
];
$scope.items = ["0"];
var style = [];
for (var i = 0; i < stylesdata.length; i++) {
style.push({
name: stylesdata[i].name,
id: stylesdata[i].id
})
}
$scope.styles = style;
})
答案 4 :(得分:0)
funcion (list)
(
loop i=0 i < 4
index = (int) length(list)*random(0 -> 1)
element[i] = list[index]
return element
)
while(check == false)
(
elements = funcion (list)
Do some calculation which returns check == false /true
)
这是伪代码,但我认为你应该自己想出来。 希望它有所帮助:)
答案 5 :(得分:0)
到目前为止,所有答案都有一个根本性的缺陷;您要求的算法将生成n
元素的随机组合,并且遵循某些逻辑规则,此组合将有效或无效。如果不是,则应生成新的组合。显然,这种新组合应该是以前从未生产过的组合。所有提出的算法都没有强制执行。例如,如果1000000
个可能的组合中只有一个是有效的,那么在产生特定的唯一组合之前,您可能会浪费大量资源。
那么,如何解决这个问题呢?嗯,答案很简单,创建所有可能的唯一解决方案,然后简单地以随机顺序生成它们。警告:我认为输入流没有重复元素,如果有,那么某些组合将不是唯一的。
首先,让我们自己写一个方便的不可变堆栈:
class ImmutableStack<T> : IEnumerable<T>
{
public static readonly ImmutableStack<T> Empty = new ImmutableStack<T>();
private readonly T head;
private readonly ImmutableStack<T> tail;
public int Count { get; }
private ImmutableStack()
{
Count = 0;
}
private ImmutableStack(T head, ImmutableStack<T> tail)
{
this.head = head;
this.tail = tail;
Count = tail.Count + 1;
}
public T Peek()
{
if (this == Empty)
throw new InvalidOperationException("Can not peek a empty stack.");
return head;
}
public ImmutableStack<T> Pop()
{
if (this == Empty)
throw new InvalidOperationException("Can not pop a empty stack.");
return tail;
}
public ImmutableStack<T> Push(T item) => new ImmutableStack<T>(item, this);
public IEnumerator<T> GetEnumerator()
{
var current = this;
while (current != Empty)
{
yield return current.head;
current = current.tail;
}
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
通过递归生成所有组合,这将使我们的生活更轻松。接下来,让我们获得主方法的签名:
public static IEnumerable<IEnumerable<T>> GetAllPossibleCombinationsInRandomOrder<T>(
IEnumerable<T> data, int combinationLength)
好的,这看起来是正确的。现在让我们实现这个:
var allCombinations = GetAllPossibleCombinations(data, combinationLength).ToArray();
var rnd = new Random();
var producedIndexes = new HashSet<int>();
while (producedIndexes.Count < allCombinations.Length)
{
while (true)
{
var index = rnd.Next(allCombinations.Length);
if (!producedIndexes.Contains(index))
{
producedIndexes.Add(index);
yield return allCombinations[index];
break;
}
}
}
好的,我们在这里所做的就是生成随机索引,检查我们还没有生成它(我们使用HashSet<int>
),并在该索引处返回组合。
很简单,现在我们只需要处理GetAllPossibleCombinations(data, combinationLength)
。
这很简单,我们将使用递归。我们的纾困条件是我们目前的组合是指定的长度。另一个警告:我在整个代码中省略了参数验证,比如检查null
或者指定的长度是否大于输入长度等等,应该注意。
为了好玩,我将在这里使用一些次要的C#7语法:嵌套函数。
public static IEnumerable<IEnumerable<T>> GetAllPossibleCombinations<T>(
IEnumerable<T> stream, int length)
{
return getAllCombinations(stream, ImmutableStack<T>.Empty);
IEnumerable<IEnumerable<T>> getAllCombinations<T>(IEnumerable<T> currentData, ImmutableStack<T> combination)
{
if (combination.Count == length)
yield return combination;
foreach (var d in currentData)
{
var newCombination = combination.Push(d);
foreach (var c in getAllCombinations(currentData.Except(new[] { d }), newCombination))
{
yield return c;
}
}
}
}
我们走了,现在我们可以使用它:
var data = "abc";
var random = GetAllPossibleCombinationsInRandomOrder(data, 2);
foreach (var r in random)
{
Console.WriteLine(string.Join("", r));
}
果然,输出是:
bc
cb
ab
ac
ba
ca