我有这种模式,我需要从列表中选择任何随机元素,而不是当前的元素(作为参数传递)。我想出了这个方法:
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”元素,并且列表不包含重复项,但是看到一些更普遍的案例也很有趣。
答案 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)];
}