【问题标题】:C# - Create Enumeraor that Get Values RandomlyC# - 创建随机获取值的 Enumeraor
【发布时间】:2014-11-27 06:34:06
【问题描述】:

我想在 C# 中创建一个 IEnumerable 类,当获取下一个值时从对象列表中随机获取它

每次我想获得下一个时我都想获得随机值,例如我的列表长度是 100,每次获得随机值时我都会获得 1000 倍的值

我创建了一个下面的类,但是当从类创建新实例时我的程序被挂起

public class MyEnumerable:System.Collections.IEnumerable
{
    public int RegionID { get; set; }

    List<Medium> RankedList;
    MediaEnumerator pe;

    public MyList(int regionID)
    {
        RegionID = regionID;
        RankedList = ShowVideo.GetRankList(regionID);
        pe = new MediaEnumerator(RankedList);
    }

    public System.Collections.IEnumerator GetEnumerator()
    {
        return (IEnumerator)(pe);
    }
}

public class MediaEnumerator : IEnumerator
{
    List<Medium> RankedList;
    int position = -1;

    public MediaEnumerator(List<Medium> list)
    {
        RankedList = list;
    }

    Random rnd = new Random();

    public bool MoveNext()
    {
        position = rnd.Next(RankedList.Count);
        return true;
    }

    public void Reset()
    {
        position = -1;
    }

    object IEnumerator.Current
    {
        get
        {
            return Current;
        }
    }

    public FileInfo Current
    {
        get
        {
            try
            {
                FileInfo fi = new FileInfo(RankedList[position].MediaUrl);
                return fi;
            }
            catch (IndexOutOfRangeException)
            {
                throw new InvalidOperationException();
            }
        }
    }
}

【问题讨论】:

  • 我假设你有问题完成迭代无限可枚举? (因为没有示例显示实际挂起的代码...)
  • 你应该发布你的真实代码。由于类和构造函数的名称不同(MyEnumerable,MyList),因此无法编译。
  • @Euphoric 我完成了问题,我的代码是真实的代码
  • @Fratyx 这个代码是我的真实代码

标签: c# ienumerable ienumerator


【解决方案1】:

使用iteratorsRandom 和无限循环将是最简单的解决方案。

public IEnumerable<T> GetRandomElements<T>(T[] elements)
{
    Random rand = new Random();
    while(true)
    {
        int index = rand.Next(0, elements.Length);
        yield return elements[index];
    }
}

【讨论】:

  • 您的回答非常喜欢,如果您喜欢,请为我的问题投票。非常感谢
【解决方案2】:

您可以通过混合 LINQ 和 GUID 以随机顺序获得 any 可枚举。

var randomOrder = originalEnumerable.OrderBy(o => new Guid());

【讨论】:

  • 每次我想获得下一个时我都想获得随机值,例如我的列表长度是 100,每次获得随机值时我都会获得 1000 倍的值
  • 每次你想要一个随机值时都调用它。 var randomValue = originalEnumerable.OrderBy(o => new GUID()).FirstOrDefault();
  • @SteveLillis 是的,并在此过程中杀死性能。并且可能分布不正确。
  • @Euphoric 与所有事物一样,在出现问题时担心性能。如果您担心分发,您可以使用 order by 中的替代随机值来满足您的分发需求。你的模式很好,但它违反了可枚举的合同,作为消费者,如果我使用 foreach,我希望能够枚举整个集合,你的将永远挂起。
  • @Euphoric 请不要屈尊俯就。 Take(x) 指定一个清晰的模式。 Skip(x) 也是,因为它们表示一个子集。 FirstOrDefault() 也再清楚不过了,Single() 也一样。 GetRandomElements(x) 还将指定 Get X Random Elements 的清晰模式。 GetRandomElements() 并不表示您将获得无限集。 “可以处理”无限序列与“将我的 10 项可枚举转换为”无限序列不同。另外值得注意的是,所有 LINQ 方法都返回一个可重现的结果集。
【解决方案3】:

我认为您的问题是您总是在 MoveNext() 中返回 true,更改此代码可能会导致您的代码正常工作

但现在有一个错误,即获取随机值的数量恰好是您的列表长度的数量。但我修复了你的代码。

    public bool MoveNext()
    {
        position++;
        return (position < RankedList.Count);
        //position = rnd.Next(RankedList.Count);
        //return true;
    }

并在 MediaEnumerator 中更改此代码

    public FileInfo Current
    {
        get
        {
            try
            {
                //FileInfo fi = new FileInfo(RankedList[position].MediaUrl);
                FileInfo fi = new FileInfo(RankedList[rnd.Next(RankedList.Count)].MediaUrl);
                return fi;
            }
            catch (IndexOutOfRangeException)
            {
                throw new InvalidOperationException();
            }
        }
    }

【讨论】:

  • 这会将所有返回项目的数量限制为与输入列表相同的数量。这不是 OP 想要的。
  • @Euphoric 我测试了这段代码并检查您的评论是否正确
猜你喜欢
  • 2015-01-27
  • 1970-01-01
  • 2011-11-01
  • 1970-01-01
  • 2011-11-29
  • 1970-01-01
  • 1970-01-01
  • 2015-10-12
  • 1970-01-01
相关资源
最近更新 更多