将SortedList转换为IOrderedEnumerable

Lia*_*amK 6 c# linq

我目前无法找到从SortedList获取IOrderedEnumerable的方法.

我有一个复杂的类型,我们现在只称它为'A',它可以被分解为一个类型'A'的枚举.我目前正在递归分解函数中创建一个SortedList,其中键a int与片段被分解的顺序相关:

private static SortedList<int, A> RecursivelyBuildMySortedList(A myValue)
{
    if (myValue == StopCondition())
    {
        return new SortedList<int, A> { { 1, myValue } };
    }

    var left = RecursivelyBuildMySortedList(myValue.Left);
    var right = RecursivelyBuildMySortedList(myValue.Right).Select(entry => new KeyValuePair<int, A>(entry.Key + left.Count, entry.Value)).ToList();
    right.ForEach(pair => left.Add(pair.Key, pair.Value));
    return left;
}
Run Code Online (Sandbox Code Playgroud)

但是,我不想将SortedList公开给消费者,因为与分解顺序相关的键的值对消费者没有什么意义(特别是作为一个int).消费者唯一需要关心的是这些碎片的最终排序是什么,以便每件都能以正确的顺序进行处理.我更愿意向消费者公开IOrderedEnumerable.我认为这将是一个相当简单的任务,因为SortedList在许多方面与OrderedEnumerable非常相似,但我还没有找到一个好的转换:

public static IOrderedEnumerable<A> Decompose(A myValue)
{
    SortedList<int, A> mySortedList = RecursivelyBuildMySortedList(myValue);

    // Can't find a way to preserve the order of the objects during 'OrderBy'
    // mySortedList.Select(keyValuePair => keyValuePair.Value).OrderBy(obj => obj.index);

    // The select statement would not match the return type that promises IOrderedEnumerable
    // mySortedList.OrderBy(keyValuePair => keyValuePair.Key).Select(keyValuePair => keyValuePair.Value);

}
Run Code Online (Sandbox Code Playgroud)

有没有人有一个从SortedList中提取IOrderedEnumerable以供消费的方法?作为旁注,我知道:

return mySortedList.Select(keyValuePair => keyValuePair.Value);
Run Code Online (Sandbox Code Playgroud)

将返回一个IEnumerable,它将保留"引擎盖下的顺序",但由于处理枚举的顺序有多重要,我宁愿返回类型足够描述以传达底层集合的有序(以使API更具可读性).

Meh*_*raz 2

您需要使用 SortedList 的 Values 属性:

  private IOrderedEnumerable<string> GetResults() {
     SortedList<int, string> list = new SortedList<int, string>();
     list.Add(40, "Mehrzad");
     list.Add(20, "Chehraz");
     return list.Values.OrderBy(key => 0);         
  }
Run Code Online (Sandbox Code Playgroud)

然后使用:

 IOrderedEnumerable<string> enumerable = GetResults();
 foreach (var item in enumerable) {
     System.Diagnostics.Debug.WriteLine(item);
 }
Run Code Online (Sandbox Code Playgroud)

它之所以有效,是因为 OrderBy (key => 0) 按原始顺序返回按 SortedList 排序的值。

或者您可以实现 IOrderedEnumerable (我的旧答案):

class OrderedEnumerableWithoutKey<TKey, TValue> : IOrderedEnumerable<TValue> {
     private IOrderedEnumerable<KeyValuePair<TKey, TValue>> inner;
     public OrderedEnumerableWithoutKey(IOrderedEnumerable<KeyValuePair<TKey, TValue>> inner) {
        this.inner = inner;
     }
     public IOrderedEnumerable<TValue> CreateOrderedEnumerable<TKey1>(Func<TValue, TKey1> keySelector, IComparer<TKey1> comparer, bool descending) {
        throw new NotImplementedException();
     }
     public IEnumerator<TValue> GetEnumerator() {
        return new Enumerator(inner.GetEnumerator());
     }
     IEnumerator IEnumerable.GetEnumerator() {
        return new Enumerator(inner.GetEnumerator());
     }
     class Enumerator : IEnumerator<TValue> {
        private IEnumerator<KeyValuePair<TKey, TValue>> inner;
        public Enumerator(IEnumerator<KeyValuePair<TKey, TValue>> inner) {
           this.inner = inner;
        }
        public TValue Current {
           get {
              return inner.Current.Value;
           }
        }
        object IEnumerator.Current {
           get {
              return inner.Current.Value;
           }
        }
        public void Dispose() {
           this.inner.Dispose();
        }
        public bool MoveNext() {
           return this.inner.MoveNext();
        }
        public void Reset() {
           this.inner.Reset();
        }
     }
  }
Run Code Online (Sandbox Code Playgroud)

然后以这种方式使用它:

private IOrderedEnumerable<string> GetResults() {
     SortedList<int, string> list = new SortedList<int, string>();
     list.Add(20, "Mehrzad");
     list.Add(10, "Chehraz");
     return new OrderedEnumerableWithoutKey<int, string>(list.OrderBy(item => item.Key));    }
..
..
// Consumer part:
IOrderedEnumerable<string> enumerable = GetResults();
foreach (var item in enumerable) {
      System.Diagnostics.Debug.WriteLine(item);
}
// Outputs:
// Cherhaz
// Mehrzad
Run Code Online (Sandbox Code Playgroud)