如何随机化数组项,然后按所需的百分比裁剪数组

时间:2010-11-07 22:17:29

标签: c#

将数组中的项随机化并删除随机项以获得所需数组长度的最佳方法是什么?

假设我有一个包含100个项目的数组。

首先,我想将其随机化。

然后,我有3%的系数:10%,30%,60%。

我想从原始数组中删除项目,因此我获得的新数组将是原始大小的60%(60项),然后是30%,然后是10%。

2 个答案:

答案 0 :(得分:5)

随机化数组的最佳方法是使用Fisher-Yates-Durstenfeld shuffle。您可以就地执行此操作(即,对现有数组进行随机播放),也可以按随机顺序创建包含项目的新集合。

以下是我可能会这样做,creating a new shuffled collection而不是改变原始数组,然后使用SkipTake来获取混洗数组所需的子序列。 (如果您愿意,可以很容易地将此​​代码更改为perform an in-place shuffle。)

// uses Shuffle extension from https://stackoverflow.com/a/1653204/55847
var temp = original.Shuffle().ToArray();
var sixty = temp.Take((int)(temp.Length * 0.6)).ToArray();
var thirty = temp.Skip(sixty.Length).Take((int)(temp.Length * 0.3)).ToArray();
var ten = temp.Skip(sixty.Length + thirty.Length).ToArray();

答案 1 :(得分:2)

好吧,首先你不能从数组中删除项目。数组的大小在创建时确定,并且在此之后永远不会更改。如果你想要一个较小的数组,你必须创建一个新数组。

您可以使用以下扩展程序对项目进行随机播放:

public static class IEnumerableExtensions {

  public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> list, Random rnd) {
    List<T> items = new List<T>(list);
    for (int i = 0; i < items.Count; i++) {
      int pos = rnd.Next(i, items.Count);
      yield return items[pos];
      items[pos] = items[i];
    }
  }

}

我不确定你的系数是什么意思,但我想你想要在一个数组中获得前60%,然后在第二个数组中获得另外30%,然后在第三个数组中获得另外10%:< / p>

IEnumerable<int> shuffled = originalArray.Shuffle(new Random()).ToList();

int cnt60 = (int)Math.Round(originalArray.Length * 0.6);
int cnt30 = (int)Math.Round(originalArray.Length * 0.3);
int cnt10 = (int)Math.Round(originalArray.Length * 0.1);

int[] first60 = shuffled.Take(cnt60).ToArray();
int[] next30 = shuffled.Skip(cnt60).Take(cnt30).ToArray();
int[] next10 = shuffled.Skip(cnt60+cnt30).Take(cnt10).ToArray();