在IList<T>中对项目进行排序

3

我有一个列表

IList<IRule> allRules = new List<IRule>()

在那个列表中,我随机添加了不同类型的规则,例如:

allRules.add(DeleteRule1)
allRules.add(AddRule1)
allRules.add(DeleteRule2) 
allRules.add(EditRule1)
allRules.add(AddRule2)
allRules.add(DeleteRule3)

所有功能运行良好,我正在努力弄清楚的是,我需要将此列表排序,以便它首先包含所有AddRules,其次是EditRules,最后是DeleteRules。

是否有人可以指定我可以采取的方法?

如果这不合理,请让我知道,我会尝试更详细地解释。

非常感谢


1
你需要为allRules.Sort()方法提供IComparer<IRule>,或者使用LambdaComparer来进行内部比较逻辑。 - sll
1
您是否希望保留每个类别内现有的顺序?也就是说,您想要得到 A1 A2 E1 D1 D2 D3 这样的结果,还是像 A2 A1 E1 D2 D3 D1 这样的顺序也可以呢? - AakashM
List<T> 有一个 Sort 方法。而 IList<T> 没有(因此问题不同)。你在示例中使用了 List,但在标题中使用了 IList - xanatos
每个类别的顺序不重要,只要所有添加在编辑之前,然后是删除... - Bobby
感谢大家的帮助 =o) - Bobby
8个回答

5

似乎没有内置的方法来对 IList<T> 进行排序。

选项1:将变量声明为 List<T> 类型,并使用List<T>.Sort 方法进行排序。

List<IRule> allRules = new List<IRule>();
allRules.add(DeleteRule);
...
allRules.Sort();

选项 2: 用一个新的有序列表替换原来的列表。

IList<IRule> allRules = new List<IRule>();
allRules.add(DeleteRule);
...
allRules = allRules.OrderBy(x => x).ToList();

选项3: 为IList<T>实现快速排序。

选项4: 选择另一种自动保持其元素以特定顺序的集合类型。


3

2
我假设你有三个类实现了IRule(AddRule,EditRule,DeleteRule)。
如果你可以将allRules的类型从IList改为List,你可以使用List<T>.Sort(Comparison<T>)方法。Comparison是一个带有以下签名的通用委托
public delegate int Comparison<in T>(T x,T y)

所以你需要像这样的东西:
public int IRuleComparer(IRule first, IRule second)
{
  //build a table of type weights (this could be made static)
  Dictionary<Type, int> typeWeights = new Dictionary<Type, int>();
  typeWeights.Add(typeof(AddRule), 1);
  typeWeights.Add(typeof(EditRule), 2);
  typeWeights.Add(typeof(DeleteRule), 3);

  //get the types of the arguments
  Type firstType = first.GetType();
  Type secondType = second.GetType();

  //are the types valid?
  if (!typeWeights.ContainsKey(firstType))
     throw new Exception("invalid first type");

  if (!typeWeights.ContainsKey(secondType))
     throw new Exception("invalid second type");

  //compare the weights of the types
  return typeWeights[firstType].CompareTo(typeWeights[secondType]);
}

另外,请注意排序实现使用的是快速排序算法,这不是一种稳定的排序算法,也就是说它可能会打乱 AddRules 的相对顺序,所以在你的例子中,AddRule2 可能会在 AddRule1 之前被排序。
或者,您可以使用LINQ并编写类似以下内容的代码:
public int GetRuleWeight(IRule item)
{
   //build a table of type weights (this could be made static)
   Dictionary<Type, int> typeWeights = new Dictionary<Type, int>();
   typeWeights.Add(typeof(AddRule), 1);
   typeWeights.Add(typeof(EditRule), 2);
   typeWeights.Add(typeof(DeleteRule), 3);

  Type itemType = item.GetType();

  if (!typeWeights.ContainsKey(itemType))
     throw new Exception("invalid type");

  return typeWeights[itemType];
}

allRules = allRules.OrderBy(item => GetRuleWeight(item)).ToList();

这将适用于 IList(甚至包括 IEnumerable),因此您不必更改 allRules 的类型。

2

您需要实现自己的IComparer,然后在Sort方法中使用它。


1

List有一个sort方法,你可以传递一个比较器(comparator),它可以为你执行比较算法。

using System;
using System.Collections.Generic;

public class Example
{
    private static int MyRuleComparer(Rule x, Rule y)
    {
      // return -1, 0 or 1 by comparing x & y
    }

    public static void Main()
    {
        List<Rule> allRules= new List<Rule>();
        allRules.Add(...);
        allRules.Add(...);
        allRules.Add(...);
        allRules.Add(...);

        allRules.Sort(MyRuleComparer);

    }
}

正如Sharique所说,您可以使用SortedList类。这个类使用IComparer实例来完成工作:

using System; using System.Collections.Generic;

public class Example
{
    public class MyComparer : IComparer  {
       int IComparer.Compare( Object x, Object y )  
       {
          // return -1, 0 or 1 by comparing x & y
       } 
    }  

    public static void Main()
    {
        SortedList allRules = new SortedList(new MyComparer ())
        allRules.Add(...); // Sorted each time
        allRules.Add(...); // Sorted each time
        allRules.Add(...); // Sorted each time
        allRules.Add(...); // Sorted each time
    }
}

1

0
我会选择简单性,因为我猜想这里不涉及到一个巨大的列表。
假设:使用C# 3,并且适当的类或接口AddRuleEditRuleDeleteRule已存在。
var sortedRules = 
           allRules.OfType<AddRule>()
   .Concat(allRules.OfType<EditRule>())
   .Concat(allRules.OfType<DeleteRule>());

0

List<T> 类

列表不保证排序。在执行需要排序的操作(如 BinarySearch)之前,必须对列表进行排序。

您可能想查看 SortedList(但它不是类型安全的),或者向 IRule 添加某种类型的 Order 字段,然后使用 IEnumerable<T>.OrderBy(...) 进行排序。

编辑

有一个 SortedList 的泛型版本


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接