LINQ OrderBy - 自定义

时间:2015-05-17 18:19:43

标签: c# linq

我有一些像

这样的数据
ID    Sequence  customIndex
1     1         0
2     2         0
3     3         2
4     4         1
5     5         0

我需要按顺序使用序列,当customIndex为零时,其他方面使用customIndex。

因此结果应该是1,2,4,3,5的顺序ID。

我需要使用Lambda实现LINQ。我尝试了一些解决方案,但无法实施。

发布重复并删除前一个,由于格式错误,问题的含义发生了变化,我收到了一堆反对票。

在dotnet小提琴上添加了代码:

https://stable.dotnetfiddle.net/fChl40

6 个答案:

答案 0 :(得分:3)

这适用于提供的测试数据:

    l.OrderBy(a => a.customIndex != 0 ? 
        list.Where(b => b.Sequence < a.Sequence && b.customIndex == 0)
            .OrderByDescending(c => c.Sequence)
            .FirstOrDefault()
            .Sequence : a.Sequence)
     .ThenBy(c=>c.customIndex )
     .ToList();

我们的想法是先通过零值行排序非零值,然后按非零值排序。

答案 1 :(得分:3)

答案基于假设,CustomIndex大于或等于零:

var result = 
    data.OrderBy(x => x.CustomIndex==0 ? x.Sequence :
            data.Where(y => y.CustomIndex==0 && y.Sequence < x.Sequence)
                .Max(y => (int?)y.Sequence))
        .ThenBy(x => x.CustomIndex);

答案 2 :(得分:0)

这是我想要的:

    public static void Main()
{
    List<Data> data = new List<Data>();
    data.Add(new Data{ Id=1, Sequence=1, CustomIndex=0});
    data.Add(new Data{ Id=5, Sequence=5, CustomIndex=0});
    data.Add(new Data{ Id=6, Sequence=6, CustomIndex=2});
    data.Add(new Data{ Id=2, Sequence=2, CustomIndex=0});
    data.Add(new Data{ Id=3, Sequence=3, CustomIndex=2});
    data.Add(new Data{ Id=4, Sequence=4, CustomIndex=1});

    data.Add(new Data{ Id=7, Sequence=7, CustomIndex=1});

    int o = 0;
    var result = data
        .OrderBy(x=>x.Sequence).ToList()
        .OrderBy((x)=> myCustomSort(x, ref o) )
            ;       
    result.ToList().ForEach(x=> Console.WriteLine(x.Id));
}

public static float myCustomSort(Data x, ref int o){

    if(x.CustomIndex==0){
        o = x.Sequence;
        return x.Sequence ;
    }
    else 
        return float.Parse(o + "."+ x.CustomIndex);
}

示例代码:https://stable.dotnetfiddle.net/fChl40 我会进一步完善它

答案 3 :(得分:0)

它很漂亮,但它可以证明你的要求,我想:

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    public static void Main()
    {
        List<Data> data = new List<Data>();
        data.Add(new Data { Id = 1, Sequence = 1, CustomIndex = 0 });
        data.Add(new Data { Id = 2, Sequence = 2, CustomIndex = 0 });
        data.Add(new Data { Id = 3, Sequence = 3, CustomIndex = 2 });
        data.Add(new Data { Id = 4, Sequence = 4, CustomIndex = 1 });
        data.Add(new Data { Id = 5, Sequence = 5, CustomIndex = 0 });

        //List of items where the sequence is what counts
        var itemsToPlaceBySequence = data.Where(x => x.CustomIndex == 0).OrderBy(x => x.Sequence).ToList();
        //List of items where the custom index counts
        var itemsToPlaceByCustomIndex = data.Where(x => x.CustomIndex != 0).OrderBy(x => x.CustomIndex).ToList();

        //Array to hold items
        var dataSlots = new Data[data.Count];

        //Place items by sequence
        foreach(var dataBySequence in itemsToPlaceBySequence) {
            dataSlots[dataBySequence.Sequence - 1] = dataBySequence ;
        }

        //Find empty data slots and place remaining items in CustomIndex order 
        foreach (var dataByCustom in itemsToPlaceByCustomIndex) {
            var index = dataSlots.ToList().IndexOf(null);
            dataSlots[index] = dataByCustom ;
        }

        var result = dataSlots.ToList();

        result.ForEach(x => Console.WriteLine(x.Id));
        var discard = Console.ReadKey();
    }

    public class Data
    {
        public int Id { get; set; }
        public int Sequence { get; set; }
        public int CustomIndex { get; set; }
    }
}

答案 4 :(得分:0)

根据您的问题并回复我的评论,我了解您需要对项目进行聚类。收集,然后在每个群集的所有项目上考虑Sequence和CustomIndex 一旦聚集(根据特定标准拆分成块),您可以将它们合并回一个唯一的集合,但在这样做时,您可以按照您需要的方式独立操作每个集群。

public static class extCluster
{
    public static IEnumerable<KeyValuePair<bool, T[]>> Clusterize<T>(this IEnumerable<T> self, Func<T, bool> clusterizer)
    {
        // Prepare temporary data
        var bLastCluster = false;
        var cluster = new List<T>();

        // loop all items
        foreach (var item in self)
        {
            // Compute cluster kind
            var bItemCluster = clusterizer(item);
            // If last cluster kind is different from current
            if (bItemCluster != bLastCluster)
            {
                // If previous cluster was not empty, return its items
                if (cluster.Count > 0)
                    yield return new KeyValuePair<bool, T[]>(bLastCluster, cluster.ToArray());

                // Store new cluster kind and reset items
                bLastCluster = bItemCluster;
                cluster.Clear();
            }

            // Add current item to cluster
            cluster.Add(item);
        }

        // If previous cluster was not empty, return its items
        if (cluster.Count > 0)
            yield return new KeyValuePair<bool, T[]>(bLastCluster, cluster.ToArray());
    }
}
// sample
static class Program
{
    public class Item
    {
        public Item(int id, int sequence, int _customIndex)
        {
            ID = id; Sequence = sequence; customIndex = _customIndex;
        }
        public int ID, Sequence, customIndex;
    }
    [STAThread]
    static void Main(string[] args)
    {
        var aItems = new[]
        {
            new Item(1, 1, 0),
            new Item(2, 2, 0),
            new Item(3, 3, 2),
            new Item(4, 4, 1),
            new Item(5, 5, 0)
        };

        // Split items into clusters
        var aClusters = aItems.Clusterize(item => item.customIndex != 0);
        // Explode clusters and sort their items
        var result = aClusters
            .SelectMany(cluster => cluster.Key
            ? cluster.Value.OrderBy(item => item.customIndex)
            : cluster.Value.OrderBy(item => item.Sequence));
    }
}

答案 5 :(得分:-1)

您要执行的排序(部分在CustomIndex上订购,部分在Sequence上订购)不能像那样工作。但这应该接近你想要的。首先按CustomIndex排序,然后按顺序排序。

var result = data.OrderBy(x => x.CustomIndex).ThenBy(x => x.Sequence);