我有以下记录

c# - Linq有点曲折-LMLPHP

最后2个是记录3和4的子代,我希望能够按金额对记录进行排序,但是应该将非利息(父母)的那些先排序,然后在他们的子代之后出现,例如像这样

2000
2000
20001
99.84 (child of the above)
50000
249.58 (child of the above)


基本上,我希望按金额排序可以忽略将“ IsInterest”设置为true的那一类,但要让它们显示在其父级之后。

我可以先将所有父母带入一个新集合中,然后再通过父母检查是否有孩子,然后在新集合中将它们插入到父母之后来做到这一点,但是我觉得这不是有效且肮脏的代码,所以我以为我会问也许有人知道黑魔法。
排序还应该知道数量上的asc / desc。

我可以发布我的代码,如果有帮助的话,将集合拆开并放在一起,但我尝试尽可能不使用该代码。

我的排序方法使用一个字符串作为“升序”或“降序”,如果有帮助的话

谢谢

更新2
我要指出的是,只有两个级别,孩子将只有一个父母(无祖父母),每个父母最多有一个孩子

根据要求更新代码(字段名称可能与db字段不同。)

 switch (sortMember.ToUpper())
            {
                case "AMOUNT":
                    {
                        //check to see if any imputed interests exist
                        if (contributions.Any(x => x.IsImputedInterest))
                        {
                            var children = contributions.Where(x => x.IsImputedInterest);
                            var sortedColl = contributions.Where(x => x.IsImputedInterest == false).OrderByWithDirection(x => x.ContributionAmount, sortDirection.ToUpper() == "DESCENDING").ToList();
                            foreach (var child  in children )
                            {
                                //find the parent
                                var parentIndex = sortedColl.FindIndex(x => x.ContributionId == child.ParentContirbutionId);
                                sortedColl.Insert(parentIndex+1, child);

                            }

                        }
                        else
                        {
                            contributions = contributions.OrderByWithDirection(x => x.ContributionAmount, sortDirection.ToUpper() == "DESCENDING");
                        }

                        break;
                    }
            }


.................

 public static IOrderedEnumerable<TSource> OrderByWithDirection<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, bool descending)
    {
        return descending ? source.OrderByDescending(keySelector)
                          : source.OrderBy(keySelector);
    }

    public static IOrderedQueryable<TSource> OrderByWithDirection<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> keySelector, bool descending)
    {
        return descending ? source.OrderByDescending(keySelector)
                          : source.OrderBy(keySelector);
    }

最佳答案

这是Linq的单个声明解决方案:

var desc = order == "descending";
var result = list
    //group parents with it's children
    .GroupBy(x => x.ParentId ?? x.Id)
    //move the parent to the first position in each group
    .Select(g => g.OrderBy(x => x.ParentId.HasValue).ThenBy(x => desc ? -x.Amount : x.Amount))
    //sort the groups by parents' amounts
    .OrderBy(g => desc ? -g.First().Amount : g.First().Amount)
    //retrieve the items from each group
    .SelectMany(g => g);


一些性能提示:


如果总是有一个孩子或您根本不在乎孩子的顺序,则可以删除ThenBy(...)
使用if语句检查顺序,并使用两个版本的语句-第二个版本使用OrderByDescending / ThenByDescending,并删除三元运算符(desc ? ... : ...)-否则将对每个项目进行评估


对于您当前的解决方案,我不提供任何性能保证-结果可能会更慢。

09-06 23:43