C#泛型秘诀(7) 2008-02-02 11:00

字号:    

4.8 反转Sorted List里的内容

问题

您希望在数组和列表类型中可以反转sorted list里的内容同时又维持SortedListSortedList<T>类原来的功能。无论是SortedList还是泛型SortedList<T>类都直接提供了完成这个功能的方法而又不需要重填列表。

解决方案

ReversibleSortedList<TKey, TValue>类提供了这些功能,它基于SortedList<TKey, TValue>类,所以拥有相同的功能,它提供了额外的功能是很容易反转已排序的列表。

在实例化ReversibleSortedList<TKey, TValue>之后,键是整数类型,值是字符串类型,一连串无序的数字和它们的文本表达被插入到列表中。这些项目是这样显示的:

ReversibleSortedList<int, string> rsl = new ReversibleSortedList<int, string>();

rsl.Add(2, "2");

rsl.Add(5, "5");

rsl.Add(3, "3");

rsl.Add(1, "1");

foreach (KeyValuePair<int, string> kvp in rsl)

{

    Debug.WriteLine("\t" + kvp.Key + "\t" + kvp.Value);

}

列表输出显示为按升序排序(默认):

    1   1
    2   2
    3   3
    5   5

现在排列顺序通过设置ReversibleSortedList的SortDirection属性被反转为降序。为了重新排序需要调用Sort()方法。结果如下:

// 转换排序方向.

rsl.Comparer.SortDirection = ListSortDirection.Descending;

// 重排列表.

rsl.Sort();

foreach (KeyValuePair<int, string> kvp in rsl)

{

    Debug.WriteLine("\t" + kvp.Key + "\t" + kvp.Value);

}

这一次,输出为降序:

    5   5
    3   3
    2   2

1   1

当把一个新项添加进列表,它将按当前的排列顺序被添加进去,但在添加完所有项后马上进行反转,就可以保持列表中元素的顺序。

    rsl.Add(4, "4");

    foreach (KeyValuePair<int, string> kvp in rsl)

    {

        Debug.WriteLine("\t" + kvp.Key + "\t" + kvp.Value);

    }

    // 转换排序方向.

    rsl.Comparer.SortDirection = ListSortDirection.Ascending;

    // 重排列表.

    rsl.Sort();

    foreach (KeyValuePair<int, string> kvp in rsl)

    {

        Debug.WriteLine("\t" + kvp.Key + "\t" + kvp.Value);

}

可以看到新项即按降序也按升序排列:

    5   5
    4   4
    3   3
    2   2
    1   1
    1   1
    2   2
    3   3
    4   4
    5   5

 

ReversibleSortedList<TKey, TValue>包含一个实现了IComparer<T>接口的嵌套类SortDirectionComparer<T>。这个类可以在“讨论”这一节中的ReversibleSortedList<TKey, TValue>代码中看到。一个实现了IComparer<T>接口的类可以做为ReversibleSortedList<TKey, TValue>构造方法的参数来改变默认的排序。IComparer<T>接口实现了Compare方法:

class Program

    {

        public int Compare(T lhs, T rhs)

        {

            int compareResult =

                lhs.ToString().CompareTo(rhs.ToString());

            // 如果为降序, 则反转

            if (SortDirection == ListSortDirection.Descending)

                compareResult *= -1;

            return compareResult;

        }

}

Compare方法使用了SortDirectionComparer<T>类的SortDirection属性来决定项的排序。这个属性在ReversibleSortedList<TKey, TValue>的内部类SortDirectionComparer<T>实例中被设置。SortDirection属性是在构造方法中被设置的,代码如下:

    public ReversibleSortedList()

    {

        this.keys = ReversibleSortedList<TKey, TValue>.emptyKeys;

        this.values = ReversibleSortedList<TKey, TValue>.emptyValues;

        this._size = 0;

        this._sortDirectionComparer = new SortDirectionComparer<TKey>();

        this._currentSortDirection = this._sortDirectionComparer.SortDirection;

}

这允许它在指定时间内反转排列顺序,但并没有重排列表中已存在的项。为了实现这个功能,需要在Reversible-SortedList<TKey, TValue>类中添加一个新的Sort()方法以重排列表。代码如下:

public void Sort()

{

    //检查是否跟现有排序方向相同.

    if (this._currentSortDirection != this._sortDirectionComparer.SortDirection)

    {

        // 如果不同,则进行反转.

        Array.Reverse(this.keys, 0, this._size);

        Array.Reverse(this.values, 0, this._size);

        // 设置当前排序.

        this._currentSortDirection = this._sortDirectionComparer.SortDirection;

     }

}

讨论

4-3是ReversibleSortedList<TKey, TValue>类的所有代码:

(译者注:这个类的代码很恐怖,接近1300行,不过代码很规范,感觉应该是商业代码,非常值得借鉴。将来有时间我会专门写文章分析它。请关注:我的博客:http://cgbluesky.blog.163.com/)

4-3 ReversibleSortedList类

[Serializable, ComVisible(false), DebuggerDisplay("Count = {Count}")]

public class ReversibleSortedList<TKey, TValue> :

        IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>,

        IEnumerable<KeyValuePair<TKey, TValue>>,

        IDictionary, ICollection, IEnumerable

{

    #region SortDirectionComparer类定义

    public class SortDirectionComparer<T> : IComparer<T>

    {   //ListSortDirection 枚举,有两个值:

        //Ascending按升序排列,Descending按降序排列

        private System.ComponentModel.ListSortDirection _sortDir;

        //构造方法

        public SortDirectionComparer()

        {   //默认为升序

            _sortDir = ListSortDirection.Ascending;

        }

        //重载构造方法

        public SortDirectionComparer(ListSortDirection sortDir)

        {

            _sortDir = sortDir;

        }

        //排序方向属性

        public System.ComponentModel.ListSortDirection SortDirection

        {

            get { return _sortDir; }

            set { _sortDir = value; }

        }

        //实现IComparer<T>接口的方法

        public int Compare(T lhs, T rhs)

        {

            int compareResult =

                lhs.ToString().CompareTo(rhs.ToString());

 

            // If order is DESC, reverse this comparison.

            if (SortDirection == ListSortDirection.Descending)

                compareResult *= -1;

            return compareResult;

        }

    }

    #endregion // SortDirectionComparer

 

    #region 构造方法

    //类型构造器

    static ReversibleSortedList()

    {

        ReversibleSortedList<TKey, TValue>.emptyKeys = new TKey[0];

        ReversibleSortedList<TKey, TValue>.emptyValues = new TValue[0];

    }

    //无参构造方法

    public ReversibleSortedList()

    {

        this.keys = ReversibleSortedList<TKey, TValue>.emptyKeys;

        this.values = ReversibleSortedList<TKey, TValue>.emptyValues;

        this._size = 0;

        this._sortDirectionComparer = new SortDirectionComparer<TKey>();

        this._currentSortDirection = this._sortDirectionComparer.SortDirection;

    }

    //用于指定排序方向的构造方法

    public ReversibleSortedList(SortDirectionComparer<TKey> comparer)

        : this()

    {

        if (comparer != null)

        {

            this._sortDirectionComparer = comparer;

            this._currentSortDirection = _sortDirectionComparer.SortDirection;

        }

    }

    //用于指定字典的构造方法

    public ReversibleSortedList(IDictionary<TKey, TValue> dictionary)

        : this(dictionary, (SortDirectionComparer<TKey>)null)

    {

    }

    //用于指定列表容量的构造方法

    public ReversibleSortedList(int capacity)

    {

        if (capacity < 0)

        {

            throw new ArgumentOutOfRangeException(

                "capacity", "Non-negative number required");

        }

        this.keys = new TKey[capacity];

        this.values = new TValue[capacity];

        this._sortDirectionComparer = new SortDirectionComparer<TKey>();

        this._currentSortDirection = _sortDirectionComparer.SortDirection;

    }

    //用于指定字典和排序方向的构造方法

    public ReversibleSortedList(IDictionary<TKey, TValue> dictionary,

                                SortDirectionComparer<TKey> comparer)

        : this((dictionary != null) ? dictionary.Count : 0, comparer)

    {

        if (dictionary == null)

        {

            throw new ArgumentNullException("dictionary");

        }

        dictionary.Keys.CopyTo(this.keys, 0);

        dictionary.Values.CopyTo(this.values, 0);

        Array.Sort<TKey, TValue>(this.keys, this.values,

                                        this._sortDirectionComparer);

        this._size = dictionary.Count;

    }

    //用于指定容量和排序方向的构造方法

    public ReversibleSortedList(int capacity, SortDirectionComparer<TKey> comparer)

        : this(comparer)

    {

        this.Capacity = capacity;

    }

    #endregion //CTORS

 

    #region 公有方法

    //添加元素

    public void Add(TKey key, TValue value)

    {

        if (key.Equals(null))

        {

            throw new ArgumentNullException("key");

        }

        int num1 = Array.BinarySearch<TKey>(this.keys, 0, this._size, key,

                                                this._sortDirectionComparer);

        if (num1 >= 0)

        {

            throw new ArgumentException("Attempting to add duplicate");

        }

        this.Insert(~num1, key, value);

    }

    //ICollection<KeyValuePair<TKey, TValue>>接口方法实现

    public void Clear()

    {

        this.version++;

        Array.Clear(this.keys, 0, this._size);

        Array.Clear(this.values, 0, this._size);

        this._size = 0;

    }

    //判断是否包含指定键

    public bool ContainsKey(TKey key)

    {

        return (this.IndexOfKey(key) >= 0);

    }

    //判断是否包含指定值

    public bool ContainsValue(TValue value)

    {

        return (this.IndexOfValue(value) >= 0);

    }

 

    public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()

    {

        return new ReversibleSortedList<TKey, TValue>.Enumerator<TKey, TValue>(

                    this);

    }

    //查找指定键

    public int IndexOfKey(TKey key)

    {

 

        if (key.Equals(null))

        {

            throw new ArgumentNullException("key");

        }

        int num1 = Array.BinarySearch<TKey>(this.keys, 0, this._size, key,

                                                this._sortDirectionComparer);

        if (num1 < 0)

        {

            return -1;

        }

        return num1;

    }

    //查找指定值

    public int IndexOfValue(TValue value)

    {

        return Array.IndexOf<TValue>(this.values, value, 0, this._size);

    }

    //IDictionary<TKey, TValue>接口方法实现

    public bool Remove(TKey key)

    {

        int num1 = this.IndexOfKey(key);

        if (num1 >= 0)

        {

            this.RemoveAt(num1);

        }

        return (num1 >= 0);

    }

    //移除指定索引元素

    public void RemoveAt(int index)

    {

        if ((index < 0) || (index >= this._size))

        {

            throw new ArgumentOutOfRangeException("index", "Index out of range");

        }

        this._size--;

        if (index < this._size)

        {

            Array.Copy(this.keys, (int)(index + 1), this.keys, index,

                        (int)(this._size - index));

            Array.Copy(this.values, (int)(index + 1), this.values, index,

                        (int)(this._size - index));

        }

        this.keys[this._size] = default(TKey);

        this.values[this._size] = default(TValue);

        this.version++;

    }

    //排序

    public void Sort()

    {

        // 检查是否跟现有排序方向相同.

        if (this._currentSortDirection !=

            this._sortDirectionComparer.SortDirection)

        {

            // 如果不同,则进行反转.

            Array.Reverse(this.keys, 0, this._size);

            Array.Reverse(this.values, 0, this._size);

            // 设置当前排序.

            this._currentSortDirection = this._sortDirectionComparer.SortDirection;

        }

    }

    //剪除多余空间

    public void TrimExcess()

    {

        int num1 = (int)(this.keys.Length * 0.9);

        if (this._size < num1)

        {

            this.Capacity = this._size;

        }

    }

    //获取指定键的值

    public bool TryGetValue(TKey key, out TValue value)

    {

        int num1 = this.IndexOfKey(key);

        if (num1 >= 0)

        {

            value = this.values[num1];

            return true;

        }

        value = default(TValue);

        return false;

    }

 

    #endregion // Public Methods

 

    #region 私有方法

    private void EnsureCapacity(int min)

    {

        int num1 = (this.keys.Length == 0) ? 4 : (this.keys.Length * 2);

        if (num1 < min)

        {

            num1 = min;

        }

        this.InternalSetCapacity(num1, false);

    }

    //返回指定索引的值

    private TValue GetByIndex(int index)

    {

        if ((index < 0) || (index >= this._size))

        {

            throw new ArgumentOutOfRangeException("index", "Index out of range");

        }

        return this.values[index];

    }

    //返回指定索引的键

    private TKey GetKey(int index)

    {

        if ((index < 0) || (index >= this._size))

        {

            throw new ArgumentOutOfRangeException("index", "Index out of range");

        }

        return this.keys[index];

    }

 

    private KeyList<TKey, TValue> GetKeyListHelper()

    {

        if (this.keyList == null)

        {

            this.keyList = new KeyList<TKey, TValue>(this);

        }

        return this.keyList;

    }

 

    private ValueList<TKey, TValue> GetValueListHelper()

    {

        if (this.valueList == null)

        {

            this.valueList = new ValueList<TKey, TValue>(this);

        }

        return this.valueList;

    }

    //在指定位置插入元素

    private void Insert(int index, TKey key, TValue value)

    {

        if (this._size == this.keys.Length)

        {

            this.EnsureCapacity(this._size + 1);

        }

        if (index < this._size)

        {

            Array.Copy(this.keys, index, this.keys, (int)(index + 1),

                         (int)(this._size - index));

            Array.Copy(this.values, index, this.values, (int)(index + 1),

                         (int)(this._size - index));

        }

        this.keys[index] = key;

        this.values[index] = value;

        this._size++;

        this.version++;

    }

 

    private void InternalSetCapacity(int value, bool updateVersion)

    {

        if (value != this.keys.Length)

        {

            if (value < this._size)

            {

                throw new ArgumentOutOfRangeException(

                   "value", "Too small capacity");

            }

            if (value > 0)

            {

                TKey[] localArray1 = new TKey[value];

                TValue[] localArray2 = new TValue[value];

                if (this._size > 0)

                {

                    Array.Copy(this.keys, 0, localArray1, 0, this._size);

                    Array.Copy(this.values, 0, localArray2, 0, this._size);

                }

                this.keys = localArray1;

                this.values = localArray2;

            }

            else

            {

                this.keys = ReversibleSortedList<TKey, TValue>.emptyKeys;

                this.values = ReversibleSortedList<TKey, TValue>.emptyValues;

            }

            if (updateVersion)

            {

                this.version++;

            }

        }

    }

 

    private static bool IsCompatibleKey(object key)

    {

        if (key.Equals(null))

        {

            throw new ArgumentNullException("key");

        }

        return (key is TKey);

    }

    //显式接口成员实现

    void ICollection<KeyValuePair<TKey, TValue>>.Add(

                                            KeyValuePair<TKey, TValue> keyValuePair)

    {

        this.Add(keyValuePair.Key, keyValuePair.Value);

    }

    //显式接口成员实现

    bool ICollection<KeyValuePair<TKey, TValue>>.Contains(

                                                 KeyValuePair<TKey, TValue> keyValuePair)

    {

        int num1 = this.IndexOfKey(keyValuePair.Key);

        if ((num1 >= 0) && EqualityComparer<TValue>.Default.Equals(this.values[num1],

                                                                   keyValuePair.Value))

        {

            return true;

        }

        return false;

    }

    //显式接口成员实现

    void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(

        KeyValuePair<TKey,TValue>[] array, int arrayIndex)

    {

        if (array == null)

        {

            throw new ArgumentNullException("array");

        }

        if ((arrayIndex < 0) || (arrayIndex > array.Length))

        {

            throw new ArgumentOutOfRangeException(

                  "arrayIndex", "Need a non-negative number");

        }

        if ((array.Length - arrayIndex) < this.Count)

        {

            throw new ArgumentException("ArrayPlusOffTooSmall");

        }

        for (int num1 = 0; num1 < this.Count; num1++)

        {

            KeyValuePair<TKey, TValue> pair1;

            pair1 = new KeyValuePair<TKey, TValue>(

                        this.keys[num1], this.values[num1]);

            array[arrayIndex + num1] = pair1;

        }

    }

    //显式接口成员实现

    bool ICollection<KeyValuePair<TKey, TValue>>.Remove(

        KeyValuePair<TKey, TValue> keyValuePair)

    {

        int num1 = this.IndexOfKey(keyValuePair.Key);

        if ((num1 >= 0) && EqualityComparer<TValue>.Default.Equals(

            this.values[num1], keyValuePair.Value))

        {

            this.RemoveAt(num1);

            return true;

        }

        return false;

    }

 

    IEnumerator<KeyValuePair<TKey, TValue>>

         IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()

    {

        return new ReversibleSortedList<TKey, TValue>.Enumerator<TKey, TValue>(

                    this);

    }

    //显式接口成员实现

    void ICollection.CopyTo(Array array, int arrayIndex)

    {

        if (array == null)

        {

            throw new ArgumentNullException("array");

        }

        if (array.Rank != 1)

        {

            throw new ArgumentException(

                "MultiDimensional array copies are not supported");

        }

        if (array.GetLowerBound(0) != 0)

        {

            throw new ArgumentException("A non-zero lower bound was provided");

        }

        if ((arrayIndex < 0) || (arrayIndex > array.Length))

        {

            throw new ArgumentOutOfRangeException(

                "arrayIndex", "Need non negative number");

        }

        if ((array.Length - arrayIndex) < this.Count)

        {

            throw new ArgumentException("Array plus the offset is too small");

        }

        KeyValuePair<TKey, TValue>[] pairArray1 =

             array as KeyValuePair<TKey, TValue>[];

        if (pairArray1 != null)

        {

            for (int num1 = 0; num1 < this.Count; num1++)

            {

                pairArray1[num1 + arrayIndex] =

                    new KeyValuePair<TKey, TValue>(this.keys[num1],

                    this.values[num1]);

            }

        }

        else

        {

            object[] objArray1 = array as object[];

            if (objArray1 == null)

            {

                throw new ArgumentException("Invalid array type");

            }

            try

            {

                for (int num2 = 0; num2 < this.Count; num2++)

                {

                    objArray1[num2 + arrayIndex] =

                           new KeyValuePair<TKey, TValue>(this.keys[num2],

                                                                this.values[num2]);

                }

            }

            catch (ArrayTypeMismatchException)

            {

                throw new ArgumentException("Invalid array type");

            }

        }

    }

    //显式接口成员实现

    void IDictionary.Add(object key, object value)

    {

        ReversibleSortedList<TKey, TValue>.VerifyKey(key);

        ReversibleSortedList<TKey, TValue>.VerifyValueType(value);

        this.Add((TKey)key, (TValue)value);

    }

    //显式接口成员实现

    bool IDictionary.Contains(object key)

    {

        if (ReversibleSortedList<TKey, TValue>.IsCompatibleKey(key))

        {

            return this.ContainsKey((TKey)key);

        }

        return false;

    }

    //显式接口成员实现

    IDictionaryEnumerator IDictionary.GetEnumerator()

    {

        return new ReversibleSortedList<TKey, TValue>.Enumerator<TKey, TValue>(

                this);

    }

    //显式接口成员实现

    void IDictionary.Remove(object key)

    {

        if (ReversibleSortedList<TKey, TValue>.IsCompatibleKey(key))

        {

            this.Remove((TKey)key);

        }

    }

    //显式接口成员实现

    IEnumerator IEnumerable.GetEnumerator()

    {

        return new ReversibleSortedList<TKey, TValue>.Enumerator<TKey, TValue>(

                this);

    }

 

 

    private static void VerifyKey(object key)

    {

        if (key.Equals(null))

        {

            throw new ArgumentNullException("key");

        }

        if (!(key is TKey))

        {

            throw new ArgumentException(

                "Argument passed is of wrong type", "key");

        }

    }

 

    private static void VerifyValueType(object value)

    {

        if (!(value is TValue) && ((value != null) || typeof(TValue).IsValueType))

        {

            throw new ArgumentException(

                "Argument passed is of wrong type", "value");

        }

    }

    #endregion // Private methods

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
网易公司版权所有 ©1997-2009