LINQ命令-自定义

本文关键字:自定义 命令 LINQ | 更新日期: 2023-09-27 17:49:25

我有一些数据像

ID    Sequence  customIndex
1     1         0
2     2         0
3     3         2
4     4         1
5     5         0

我需要使用顺序时,customIndex为零,否则使用customIndex。

所以结果应该是ID按1、2、4、3、5的顺序。

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

发布副本并删除前一个,因为错误的格式改变了问题的含义,我收到了一堆反对票。

在dotnet fiddle:

添加代码https://stable.dotnetfiddle.net/fChl40

LINQ命令-自定义

答案基于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);

这是为提供的测试数据工作:

    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();

这个想法是通过首先在零值行之前排序非零值,然后通过非零值本身排序。

这是我想要的:

    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我将进一步细化

根据你的问题和对我评论的回复,我明白你需要对项目集合进行聚类,然后考虑每个集群的所有项目的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));
    }
}

它不漂亮,但它体现了你的要求,我认为:

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; }
    }
}

您想要做的排序(部分在CustomIndex上排序,部分在Sequence上排序)不是这样工作的。但这应该接近你想要的结果。先按CustomIndex排序,再按Sequence排序。

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