首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将SortedList转换为IOrderedEnumerable

将SortedList转换为IOrderedEnumerable
EN

Stack Overflow用户
提问于 2015-05-12 19:21:42
回答 3查看 2.6K关注 0票数 6

我目前很难找到从IOrderedEnumerable中获取SortedList的方法。

我有一个复杂的类型,我们现在把它叫做'A‘,它可以分解成一个类型'A’的计数。我目前正在一个递归分解函数中创建一个SortedList,其中键int与块被分解的顺序相关:

代码语言:javascript
复制
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;
}

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

代码语言:javascript
复制
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);

}

是否有人有从IOrderedEnumerable中提取供消费的SortedList的方法?顺便提一句,我知道:

代码语言:javascript
复制
return mySortedList.Select(keyValuePair => keyValuePair.Value);

将返回一个保留顺序的IEnumerable,但由于处理可枚举的顺序是多么重要,我宁愿返回类型足够描述,以传达底层集合是有序的(以提高API的可读性)。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-05-12 19:43:06

您需要使用SortedList的值属性:

代码语言:javascript
复制
  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);         
  }

然后使用:

代码语言:javascript
复制
 IOrderedEnumerable<string> enumerable = GetResults();
 foreach (var item in enumerable) {
     System.Diagnostics.Debug.WriteLine(item);
 }

它可以工作,因为OrderBy (键=> 0)以原始顺序返回值,这些值是按SortedList排序的。

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

代码语言:javascript
复制
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();
        }
     }
  }

然后以这样的方式使用:

代码语言:javascript
复制
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
票数 2
EN

Stack Overflow用户

发布于 2015-05-12 19:57:48

IOrderedEnumerable的公共实现不可用。你得自己动手。

Enumerable.OrderByEnumerable.OrderByDescending的帮助下,这是相当简单的。使用尽可能少的代码,请参见下面的实现。

代码语言:javascript
复制
public class SortedListOrderedEnumerable<TKey, TValue> : IOrderedEnumerable<TValue>
{
    private readonly SortedList<TKey, TValue> innerList;
    public SortedListOrderedEnumerable(SortedList<TKey, TValue> innerList)
    {
        this.innerList = innerList;
    }

    public IOrderedEnumerable<TValue> CreateOrderedEnumerable<TKey1>(Func<TValue, TKey1> keySelector, IComparer<TKey1> comparer, bool @descending)
    {
        return @descending 
            ? innerList.Values.OrderByDescending(keySelector, comparer) 
            : innerList.Values.OrderBy(keySelector, comparer);
    }

    public IEnumerator<TValue> GetEnumerator()
    {
        return innerList.Values.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

public static class Ext
{
    public static IOrderedEnumerable<TValue> AsOrderedEnumerable<TKey, TValue>(
        this SortedList<TKey, TValue> list)
    {
        return new SortedListOrderedEnumerable<TKey, TValue>(list);
    } 
}

然后用它作为

代码语言:javascript
复制
SortedList<int, string> list = new SortedList<int, string>();
...
var ordered = list.AsOrderedEnumerable()
    .ThenBy(...)
    .ThenByDescending(...);

现在你的分解方法会变成

代码语言:javascript
复制
public static IOrderedEnumerable<A> Decompose(A myValue)
{
    SortedList<int, A> mySortedList = RecursivelyBuildMySortedList(myValue);        
    return mySortedList.AsOrderedEnumerable();
}

编辑:更新了我的初始答案以返回IOrderedEnumerable<TValue>,在原来的答案中,它是IOrderedEnumerable<KeyValuePair<TKey,TValue>>

票数 2
EN

Stack Overflow用户

发布于 2015-05-12 20:23:45

您可能不想为此使用IOrderedEnumerable

IOrderedEnumerable只存在于像ThenBy(...)这样的东西,您在运行时动态地指定排序顺序(实际上,只是构建一个比较器)。

另一方面,SortedList有一个固定的排序顺序和比较器--它的排序不能改变。

我建议坚持普通的IEnumerable,除非你有一个很好的理由,你还没有说。记住,接口并不是用来记录类型的(也就是说,通过说“这是有序的”)。他们是来揭露功能的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30199697

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档