Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 带扭曲的Linq排序_C#_Performance_Linq - Fatal编程技术网

C# 带扭曲的Linq排序

C# 带扭曲的Linq排序,c#,performance,linq,C#,Performance,Linq,我有以下记录 最后2个是记录3和4的子项,我希望能够按数量对记录进行排序,但应该是先对非兴趣(家长)的记录进行排序,然后他们的孩子应该在之后出现,例如 2000 2000 20001 99.84 (child of the above) 50000 249.58 (child of the above) 基本上,我希望我的排序数量忽略“IsInterest”设置为true的那一个,但让它们出现在它们的父母之后 我可以先把所有的父母都带到一个新的收藏中去。。然后通过父项查看是否有子项,然后将它

我有以下记录

最后2个是记录3和4的子项,我希望能够按数量对记录进行排序,但应该是先对兴趣(家长)的记录进行排序,然后他们的孩子应该在之后出现,例如

2000
2000
20001
99.84 (child of the above)
50000
249.58 (child of the above)
基本上,我希望我的排序数量忽略“IsInterest”设置为true的那一个,但让它们出现在它们的父母之后

我可以先把所有的父母都带到一个新的收藏中去。。然后通过父项查看是否有子项,然后将它们插入新集合中的父项之后,但我觉得这不是有效且肮脏的代码,所以我想我会问可能有人知道黑魔法。 分拣员还应了解金额上的asc/desc

如果有帮助的话,我可以发布我的代码,把收藏拆开并放在一起,但如果可能的话,我会尽量不使用这些代码

我的排序方法使用字符串表示“升序”或“降序”,如果这样有帮助的话

多谢各位

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

根据请求更新代码(字段名称可能不同于数据库字段..)

 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);
    }
public static IOrderedEnumerable OrderByWithDirection(此IEnumerable源代码,Func键选择器,布尔递减)
{
返回降序?source.OrderByDescending(keySelector)
:source.OrderBy(keySelector);
}
公共静态IOrderedQueryable OrderByWithDirection(此IQueryable源、表达式键选择器、布尔降序)
{
返回降序?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);
一些性能提示:

  • 如果总是最多有一个孩子,或者您不关心孩子的顺序,那么您可以先删除
    ,然后再删除(…)
  • 使用
    if
    语句检查顺序,并有两个版本的语句-第二个版本使用
    OrderByDescending
    /
    然后使用bydescending
    ,并删除三元运算符(
    desc?…:
    )-否则将对每个项目求值

我不会就您当前的解决方案的性能提供任何保证-它可能会变得更慢。

您可以使用以下通用方法(不受级别或父/子级数量的限制):

更新:事实证明,事情并不是那么简单。虽然上面的方法为叶元素以及元素对其父元素提供了正确的顺序,但它不能正确地对父元素进行排序。正确的方法如下(从这里使用另一个可重用方法,因此如果我们不计算它实际上并不比前面的方法大多少):


向我们展示您当前的排序方法。您可以在
OrderBy
/
OrderByDescending
之后使用
ThenBy
/
OrderByDescending
进行排序。您将如何做到这一点,它将第一次对它们进行排序,99.83249.582000。。。。。这不是我想在这个网站上得到的帮助,你应该遵守它的规则/期望。也就是说:按照Ivan的建议,首先自己尝试一下,让我们看看你做了什么。在任何情况下,我已经说了所有你需要知道的:使用LINQ,你可以通过使用
然后使用
/
然后使用Descending
@IvanStoev code postedas在主线程中更新,迭代地重新排序(首先根据特定的条件,然后根据不同的条件,等等),只会有一个子项,而且只有一代人(只有父母有一个孩子)不涉及祖父母
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);
public static class Extensions
{
    public static IEnumerable<T> ThenByHierarchy<T, TKey>(this IOrderedEnumerable<T> source, Func<T, TKey> keySelector, Func<T, TKey> parentKeySelector)
    {
        var itemByKey = source.ToDictionary(keySelector);
        var processSet = new HashSet<T>();
        var stack = new Stack<T>();
        foreach (var item in itemByKey.Values)
        {
            for (var next = item; processSet.Add(next); )
            {
                stack.Push(next);
                if (!itemByKey.TryGetValue(parentKeySelector(next), out next)) break;
            }
            while (stack.Count != 0)
                yield return stack.Pop();
        }
    }
}
var result = contributions
    .OrderByWithDirection(x => x.ContributionAmount, sortDirection.ToUpper() == "DESCENDING")
    .ThenByHierarchy(x => x.ContributionId, x => x.ParentContirbutionId);
public static class Extensions
{
    public static IEnumerable<T> HierarchicalOrder<T, TKey>(this IEnumerable<T> source, Func<T, TKey> keySelector, Func<T, TKey> parentKeySelector, Func<IEnumerable<T>, IOrderedEnumerable<T>> order)
    {
        // Collect parent/child relation info
        var itemById = source.ToDictionary(keySelector);
        var childListById = new Dictionary<TKey, List<T>>();
        var rootList = new List<T>();
        foreach (var item in itemById.Values)
        {
            var parentKey = parentKeySelector(item);
            List<T> childList;
            if (parentKey == null || !itemById.ContainsKey(parentKey))
                childList = rootList;
            else if (!childListById.TryGetValue(parentKey, out childList))
                childListById.Add(parentKey, childList = new List<T>());
            childList.Add(item);
        }
        // Traverse the tree using in-order DFT and applying the sort on each sublist
        return order(rootList).Expand(item =>
        {
            List<T> childList;
            return childListById.TryGetValue(keySelector(item), out childList) ? order(childList) : null;
        });
    }
    public static IEnumerable<T> Expand<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> elementSelector)
    {
        var stack = new Stack<IEnumerator<T>>();
        var e = source.GetEnumerator();
        try
        {
            while (true)
            {
                while (e.MoveNext())
                {
                    var item = e.Current;
                    yield return item;
                    var elements = elementSelector(item);
                    if (elements == null) continue;
                    stack.Push(e);
                    e = elements.GetEnumerator();
                }
                if (stack.Count == 0) break;
                e.Dispose();
                e = stack.Pop();
            }
        }
        finally
        {
            e.Dispose();
            while (stack.Count != 0) stack.Pop().Dispose();
        }
    }
}
var result = contributions
    .HierarchicalOrder(x => x.ContributionId, x => x.ParentContirbutionId, c =>
    .OrderByWithDirection(x => x.ContributionAmount, sortDirection.ToUpper() == "DESCENDING"));