65.9K
CodeProject 正在变化。 阅读更多。
Home

使用扩展方法向泛型列表添加随机功能

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.40/5 (3投票s)

2009年4月28日

CPOL

2分钟阅读

viewsIcon

25449

downloadIcon

185

扩展 IList 以包含一个洗牌方法和一个“随机选择元素”方法。

引言

.NET Framework 提供了大量用于操作列表的功能。然而,经常出现的需求是能够将列表重新排序为随机序列,或者从列表中随机选择一个元素。这两者都相对简单,并且可以通过在 IList<T> 上使用一对扩展方法来实现,这意味着它们将可用于任何 List<T>ObservableCollection<T> 以及从它们派生的任何类。

注意:本文已更新,请滚动到页面底部查看历史记录。

选择随机元素

可以使用扩展方法实现一个选择随机元素的方法,但必须位于一个 static 类中。

需要注意的是,Random.Next 返回一个介于 0 list.Count – 1 之间的值,即小于指定的最大值(另外,我实际上有一个 Random 的扩展方法,可以使用包含参数值的返回值)。语句 default(T) 用于因为值类型不能设置为 null (例如,int int? 相对)。

private static Random random = new Random();
 
public static T GetRandom<T>(this IList<T> list)
{
  if (list.Count == 0)
  {
    return default(T);
  }
  return list[random.Next(0, list.Count)];
}

重新排序列表

既然我们已经了解了 Random 的味道,那么如何操作列表中的元素呢? 同样,扩展方法提供了一种简洁的方法来做到这一点

public static void Shuffle <T>(this IList <T> list) 
{ 
  if (list.Count <= 1) 
  { 
    return; // nothing to do 
  } 
  
  for (int i = 0; i < list.Count; i++) 
  { 
    int newIndex = random.Next(0, list.Count); 
    
    // swap the two elements over 
    T x = list[i]; 
    list[i] = list[newIndex]; 
    list[newIndex] = x; 
  }
}

它的工作原理是循环遍历列表中的每个元素,并将其与随机选择位置的另一个元素交换。 请注意,与许多事情一样,当列表相对较小时,此代码可以正常工作,但讨论列表操作的优化超出了本文的范围。

结论

这些方法只是列表可以扩展以包含产生随机输出的功能的两种示例,并且通过将其放置在基础泛型接口上,可以实现跨大量类的重用。

历史

  • 版本 1.0
    • 首次发布
  • 版本 1.1
    • 更新了洗牌算法,使其真正随机
    • 改进了示例
© . All rights reserved.