English 中文(简体)
我如何指定只有在有领带时才使用Linq TextBy条款?
原标题:How can I specify to use Linq ThenBy clause only when there is a tie?

我有一个Linq 查询(与数据库无关) 与OrordBy 和 ThenBy 连接

var sortedList = unsortedList
                .OrderBy(foo => foo.Bar) //this property access is relatively fast
                .ThenBy(foo => foo.GetCurrentValue()) //this method execution is slow

获取 foo. bar 是快速的, 但执行 foo. GetCrentValue () 执行速度非常慢。 只有当某些成员拥有相等的 bar 值时, 返回值才重要, 这很少发生, 但在发生时必须加以考虑 。 是否可能选择只执行在相同 bar 值情况下需要断线的TextBy 条款? (即如果 foo. bar 值是独一无二的, 则不会执行 ) 。

另外,律师也有点慢,所以最好不要为同一对象援引两次。

最佳回答

这有点笨拙,但我相信它可以改进-也许在一个语句中不会完成,但应该有效:

var sortedList2 = unsortedList
                .OrderBy(foo => foo.Bar)
                .GroupBy(foo => foo.Bar);

            var result = new List<Foo>();
            foreach (var s in sortedList2)
            {
                if (s.Count() > 1)
                {
                    var ordered = s
                        .OrderBy(el => el.GetCurrentValue());
                    result.AddRange(ordered);
                }
                else
                {
                    result.AddRange(s);
                }
            }

UPDATE:
We can argue if that s an improvement, but it looks more concise at least:

var list3 = (from s in sortedList2
             let x = s.Count()
             select x == 1 
                    ? s.Select(el => el) 
                    : s.OrderBy(el => el.GetCurrentValue()))
             .SelectMany(n => n);

<强> UPATE2:

您可以使用 Skip(1). Any() 而不是 Count() - 这将避免列出整个序列。

问题回答

因为您不在数据库中, 需要严格控制分类, 您可以使用一个自定义的 Icomparer, 仅访问它需要的东西, 而不进行不必要的评估 。

var query = unsortedList
  .GroupBy(foo => foo.Bar)
  .OrderBy(g => g.Key)
  .SelectMany(g => g.Skip(1).Any() ? g.OrderBy(foo => foo.GetCurrentValue()) : g);

这显然具有不返回 IOderedEnumberable< Foo> 的负面效果。

我改变了Joanna Turban的解决方案 并开发了以下推广方法:

public static IEnumerable<TSource> OrderByThenBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> orderBy, Func<TSource, TKey> thenBy)
{
    var sorted = source
        .Select(s => new Tuple<TSource, TKey>(s, orderBy(s)))
        .OrderBy(s => s.Item2)
        .GroupBy(s => s.Item2);

    var result = new List<TSource>();
    foreach (var s in sorted)
    {
        if (s.Count() > 1)
            result.AddRange(s.Select(p => p.Item1).OrderBy(thenBy));
        else
            result.Add(s.First().Item1);
    }
    return result;
}

试试这个

var sortedList = unsortedList.OrderBy(foo => foo.Bar);

if(some_Condition)
{ 
   sortedList = sortedList.OrderBy(foo => foo.GetCurrentValue()); 
}




相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签