我想从N个元素的列表中统一选择K个元素,而不需要对列表进行混洗。所以算法应该总是产生相同的结果。
E.g。
int N = 100;
List<int> myList = Enumerable.Range(0, N-1).ToList();
int K = 20;
我希望结果如下:
0, 5, 10, 15, 20, ...
E.g。
if K == 50
我希望:0, 2, 4, 6, 8, ...
但是我不知道如何解决它,例如K = 53?我仍然想从列表中获取统一的元素,但在这种情况下,我们不能简单地从列表中获取每个第二个元素。简单的方法是对元素进行混洗并从列表中取出第一个K
元素,再次对列表进行排序,但在这种情况下,算法的结果每次都会产生不同的结果,每次都需要相同的结果。
任何帮助都将不胜感激。
答案 0 :(得分:4)
如果它们都是等距的,则查找索引是什么,并舍入到最接近的整数。
int N = 100;
List<int> myList = Enumerable.Range(0, N).ToList();
double K = 53;
List<int> solutions=new List<int>();
for (int i=1;i<=K;i++)
{
solutions.Add(myList[(int)Math.Round(i*(N/K)-1)]);
}
Console.WriteLine(solutions.Count);
Console.WriteLine(string.Join(", ", solutions));
查看示例:DEMO
编辑:Math.Floor
的效果优于Math.Round
,因为Math.Round
为N = 5,K = 3提供了错误的解决方案:
Math.Round->1,2,4
Math.Floor->0,2,4
查看示例:DEMO2
答案 1 :(得分:0)
此问题与线条绘制算法完全相同:https://en.wikipedia.org/wiki/Line_drawing_algorithm
在您的情况下,您想要从(0,0)到(20,52)
画一条线答案 2 :(得分:-1)
你仍然可以随机播放列表。请参阅以下示例
var n = 100;
var k = 53;
var originalList = GetListWithNElements(n);
var shuffledList = ShuffleList(originalList);
var firstKElements = GetFirstKElements(k, shuffledList);
[...]
List<int> GetListWithNElements(int n)
{
return Enumerable.Range(0, n-1).ToList();
}
List<int> ShuffleList(List<int> originalList)
{
List<int> copy = originalList.ToList();
List<int> result = new List<int>();
Random randomGenerator = new Random(314159);
while(copy.Any())
{
int currentIndex = randomGenerator.Next(copy.Count);
result.Add(copy[currentIndex]);
copy.RemoveAt(currentIndex);
}
return result;
}
List<int> GetFirstKElements(int k, List<int> shuffledList)
{
return shuffledList.Take(k).ToList();
}
Random
使用常量种子进行初始化,因此每次都会产生相同的“random”值序列,因此每次都会使用相同的元素。
答案 3 :(得分:-2)
请尝试以下操作:
static void Main(string[] args)
{
const int N = 100;
{
List<int> myList = Enumerable.Range(0, N - 1).ToList();
int seed = 5;
int numberOfItems = 50;
List<int> results = TakeNItems(myList, seed, numberOfItems);
}
}
static List<int> TakeNItems(List<int> data, int seed, int numberOfItems)
{
Random rand = new Random(seed);
return data.Select((x,i) => new { x = x, index = i, rand = rand.Next()})
.OrderBy(x => x.rand)
.Take(numberOfItems)
.OrderBy(x => x.index)
.Select(x => x.x)
.ToList();
}