Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/257.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 对列表包装器类进行排序_C#_Sorting_Random - Fatal编程技术网

C# 对列表包装器类进行排序

C# 对列表包装器类进行排序,c#,sorting,random,C#,Sorting,Random,我有一个类,它包装了一个列表,并添加了处理比率的功能。它需要在不同的时间以两种方式进行分类;按顺序排列,按比例大小排列 以下是我目前使用的按顺序位置排序的方法,我想以此作为两个相关问题的基础: 有没有更好的方法 我将如何使用IComparer进行此操作 传入IComparer的主要动机是允许不同的实现随机地洗牌列表。但是在代码中我看不到任何解析。我正在寻找一些示例代码和它的用法,这样我就可以对它了如指掌了 干杯, 贝里尔 // ///维护适合在分配中使用的比率列表 ///所有项目的总和正好等于一

我有一个类,它包装了一个列表,并添加了处理比率的功能。它需要在不同的时间以两种方式进行分类;按顺序排列,按比例大小排列

以下是我目前使用的按顺序位置排序的方法,我想以此作为两个相关问题的基础:

  • 有没有更好的方法
  • 我将如何使用IComparer进行此操作
  • 传入IComparer的主要动机是允许不同的实现随机地洗牌列表。但是在代码中我看不到任何解析。我正在寻找一些示例代码和它的用法,这样我就可以对它了如指掌了

    干杯,
    贝里尔

    //
    ///维护适合在分配中使用的比率列表
    ///所有项目的总和正好等于一(100%)。任何个人都不能这样做
    ///小于零或大于一。
    /// 
    公共类比率:IList
    {
    私有只读IList_items=new List();
    私有随机数;
    公共无效命令(索引排序命令){
    IList ordered=null;
    开关(订购)
    {
    case IndexOrdering.FirstToLast:
    打破
    案例IndexOrdering.LastToFirst:
    有序=this.Reverse().ToList();
    打破
    案例索引排序。随机:
    如果(_rnd==null)_rnd=new Random();
    有序=可枚举。范围(0,计数)
    .OrderBy(x=>\u rnd.Next())
    .选择(索引=>此[索引])
    .ToList();
    打破
    违约:
    抛出新ArgumentOutOfRangeException(“排序”);
    }
    if(ordered==null)返回;
    清除();
    foreach(已订购的var ra){
    添加(ra);
    }
    }
    
    您的方法的性能不是最佳的,因为您没有进行就地排序。相反,您将每个项目复制两次。首先在调用
    ToList
    中,然后在调用
    Add

    IComparer
    接口与执行就地排序的方法结合使用。因此,这应该是一种方法


    您首先需要将
    \u项的类型更改为
    列表

    对于您想要支持的每个排序,您需要创建一个实现
    IComparer
    的新类。如果这些类不用于其他地方,您可以将它们作为私有类放在
    RatioBag

    然后,您的
    Order
    方法将如下所示:

    public void Order(IndexOrdering ordering)
    {
        switch (ordering)
        {
            case IndexOrdering.FirstToLast:
                _items.Sort(new AscendingComparer());
                break;
            case IndexOrdering.LastToFirst:
                _items.Sort(new DescendingComparer());
                break;
            case IndexOrdering.Random:
                _items.Sort(new RandomComparer());
                break;
            default:
                throw new ArgumentOutOfRangeException("ordering");
        }
    }
    

    但是,我建议删除
    索引排序
    枚举,并为每种排序类型提供一种排序方法。代码会更干净。

    您的方法的性能不是最佳的,因为您没有进行就地排序。相反,您要将每个项复制两次。首先在调用
    ToList
    然后在对
    的调用中添加

    IComparer
    接口与执行就地排序的方法结合使用。因此,这应该是一种方法


    您首先需要将
    \u项的类型更改为
    列表

    对于您想要支持的每个排序,您需要创建一个实现
    IComparer
    的新类。如果这些类不用于其他地方,您可以将它们作为私有类放在
    RatioBag

    然后,您的
    Order
    方法将如下所示:

    public void Order(IndexOrdering ordering)
    {
        switch (ordering)
        {
            case IndexOrdering.FirstToLast:
                _items.Sort(new AscendingComparer());
                break;
            case IndexOrdering.LastToFirst:
                _items.Sort(new DescendingComparer());
                break;
            case IndexOrdering.Random:
                _items.Sort(new RandomComparer());
                break;
            default:
                throw new ArgumentOutOfRangeException("ordering");
        }
    }
    

    但是,我建议删除
    索引排序
    枚举,并为每种排序类型提供一种排序方法。代码会更干净。

    为什么不应该使用三种不同的方法而不是一种呢?

    为什么不应该使用三种不同的方法而不是一种呢?

    马上,我看不出你能做多少除了尽可能避免调用此方法外,它的速度更快,因为排序和重建列表本身就很慢:-)。一种可能的选择是使用SortedSet,这将使集合保持排序顺序,从而帮助您避免每次更改集合时都要诉诸的相关成本呃,我想当您更改排序策略时(尽管我敢打赌SortedSet实现人员在编写代码时一定会考虑到这一点)

    我想这并不能真正回答您的问题,但您是否可以将Func传递给Order()方法(并放弃IndexOrdering枚举),然后将该Func直接传递给OrderBy()呢方法?这将允许您在不接触该类的情况下表达各种疯狂的排序方法,并且您可以从该类中删除任何不必要的状态包袱(如_rnd,如果它不在其他任何地方使用的话)

    比如:

    public class RatioBag : IList<RatioAssociation>
    {
        private readonly IList<RatioAssociation> _items = new List<RatioAssociation>();
    
        public void Order(Func<RatioAssociation, int> func) {
            var ordered = _items.OrderBy(func);
            _items.Clear();
            ((List<RatioAssociation>)_items).AddRange(ordered);
        }
    }
    
    IComparer解决方案也可以实现类似的解决方案

    希望这有帮助


    Nate

    一开始,除了尽可能避免调用此方法外,我真的看不到你能做多少事情来加快它,因为排序和重建列表本身就很慢:-)。一个可能的选择是使用SortedSet,它将保持集合的排序顺序,从而帮助你避免与排序相关的成本每次更改集合时进行ESORT。虽然我认为在更改排序策略时没有多大帮助(尽管我敢打赌SortedSet实现人员在编写代码时一定考虑过这一点)

    我想这并不能真正回答您的问题,但您是否可以将Func传递给Order()方法(并放弃IndexOrdering枚举),然后将该Func直接传递给OrderBy()呢方法?这将允许您在不接触此类的情况下表达各种疯狂的排序方法,并且您可以删除
    var myCollection = new RatioBag();
    myCollection.Order(item => item.PropertyX);
    myCollection.Order(item => item.PropertyY);
    var r = new Random();
    myCollection.Order(item => r.Next());