从IList<>中选择一个随机元素除了这一个

时间:2009-09-08 11:22:39

标签: c#

我有这种模式,我需要从列表中选择任何随机元素,而不是当前的元素(作为参数传递)。我想出了这个方法:

public Element GetAnyoneElseFromTheList(Element el)
{
  Element returnElement = el;
  Random rndElement = new Random();
  if (this.ElementList.Count>2) 
  {
  while (returnElement == el) 
  {
    returnElement = this.ElementList[rndElement.Next(0,this.ElementList.Count)];  
  }

  return returnElement;
  }
 else return null;
}

但是,虽然循环一直困扰着我几天,我需要睡一会儿。还有其他好办法吗?即。以固定步数返回的东西?

编辑:在我的情况下,列表保证包含要避免的“el”元素,并且列表不包含重复项,但是看到一些更普遍的案例也很有趣。

6 个答案:

答案 0 :(得分:8)

public Element GetAnyoneElseFromTheList(Element el)
{
  if(this.ElementList.Count < 2) return null;
  Random rndElement = new Random();
  int random = rndElement.Next(0,this.ElementList.Count -1);
  if(random >= this.ElementList.indexOf(el)) random += 1;
  return this.ElementList[random];
}

获取0到列表长度减去2之间的随机数。

如果该数字大于或等于元素的索引,请为该数字添加一个。

返回该数字索引处的元素

编辑: 有人在评论中提到,他们随后删除了如果您有重复项,这种方法效果不佳。 在这种情况下,最佳解决方案实际上就是。

public Element GetAnyoneElseFromTheList(int elId)
{
  if(elId >= this.ElementList.Count) throw new ArgumentException(...)
  if(this.ElementList.Count < 2) return null;
  Random rndElement = new Random();
  int random = rndElement.Next(0,this.ElementList.Count -1);
  if(random >= elId) random += 1;
  return this.ElementList[random];
}

编辑2:重复元素的另一种替代方法是,您可以对列表的克隆版本使用优化的随机排序(随机排序)操作,然后遍历列表。 foreach将迭代到列表中的重复元素的数量。这一切都取决于你的随机算法的优化程度。

答案 1 :(得分:7)

public Element GetAnyoneElseFromTheList(Element el)
{
  Random rndElement = new Random();
  int index;
  if (this.ElementList.Count>1) 
  {
     index = rndElement.Next(0,this.ElementList.Count-1);
     if (this.ElementList[index] == el)
        return this.ElementList[this.ElementList.Count-1];
     else
        return this.ElementList[index];
  }
 else return null;
}

答案 2 :(得分:2)

我必须解决类似的问题。这就是我要做的事情:

public Element GetAnyoneElseFromTheList(Element el)
{   
     // take a copy of your element list, ignoring the currently selected element
     var temp = this.ElementList.Where(e => e != el).ToList();
     // return a randomly selected element
     return temp[new Random().Next(0, temp.Count)];
}

答案 3 :(得分:2)

首先计算要避免的匹配元素数量。然后根据剩余的项目选择一个随机数,并找到所选项目:

public Element GetAnyoneElseFromTheList(Element el) {
   int cnt = this.ElementList.Count(e => e != el);
   if (cnt < 1) return null;
   Random rand = new Random();
   int num = rand.Next(cnt);
   index = 0;
   while (num > 0) {
      if (this.ElementList[index] != el) num--;
      index++;
   }
   return this.ElementList[index];
}

答案 4 :(得分:2)

public Element GetAnyoneElseFromTheList(Element el)
{
    // first create a new list and populate it with all non-matching elements
    var temp = this.ElementList.Where(i => i != el).ToList();

    // if we have some matching elements then return one of them at random
    if (temp.Count > 0) return temp[new Random().Next(0, temp.Count)];

    // if there are no matching elements then take the appropriate action
    // throw an exception, return null, return default(Element) etc
    throw new Exception("No items found!");
}

如果您不使用C#3和/或.NET 3.5,那么您需要稍微改变一下:

public Element GetAnyoneElseFromTheList(Element el)
{
    // first create a new list and populate it with all non-matching elements
    List<Element> temp = new List<Element>();
    this.ElementList.ForEach(delegate(int i) { if (i != el) temp.Add(i); });

    // if we have some matching elements then return one of them at random
    if (temp.Count > 0) return temp[new Random().Next(0, temp.Count)];

    // if there are no matching elements then take the appropriate action
    // throw an exception, return null, return default(Element) etc
    throw new Exception("No items found!");
}

答案 5 :(得分:1)

怎么样:

 public Element GetAnyoneElseFromTheList(Element el)
  {
  Random rand = new Random();
  Element returnEle = ElementList[rand.Next(0, this.ElementList.Count];
  return returnEle == el ? GetAnyoneElseFromTheList(Element el) : el;
 }

或者你不喜欢循环的可能性:

public Element GetAnyoneElseFromTheList(Element el)
 {
  Random rand = new Random();
  List<Element> listwithoutElement = ElementList.Where(e=>e != el).ToList();
  return listwithoutElement[rand.Next(listwithoutElement.Count)];
 }