按多个属性排序

时间:2018-04-12 09:16:33

标签: c# linq

我有这样的名单,我想点这个

  • 首先是" ab"
  • 然后按照" ab"
  • 按列表中的字母顺序排列
  • 然后通过" cd"
  • 然后通过" cd"
  • 按列表中的字母顺序排列
  • 然后由" ef"
  • 然后通过" ef"
  • 按列表中的字母顺序排列

然后按字母顺序排列

我有这个linq查询

var groups =  profileModel.Groups.
OrderByDescending(i => i.FullName.ToLower().Contains("ab")).
ThenByDescending(i => i.FullName.ToLower().Contains("cd")).
ThenByDescending(i => i.FullName.ToLower().Contains("ef"));

我应该如何扩展这个?我必须使用分组吗?

4 个答案:

答案 0 :(得分:0)

您似乎想要这个,然后无需使用GroupBy

var groupOrders = new List<string> { "ab", "cd", "ef" };

var resultList = profileModel.Groups
    .Select(x => new { ModelGroup = x, First2Letter = x.FullName.Substring(Math.Min(2, x.FullName.Length)) })
    .Select(x => new
    {
        x.ModelGroup,
        x.First2Letter,
        Index = groupOrders.FindIndex(s => s.Equals(x.First2Letter, StringComparison.OrdinalIgnoreCase))
    })
    .OrderByDescending(x => x.Index >= 0) // first all known groups
    .ThenBy(x => x.Index)
    .ThenBy(x => x.ModelGroup.FullName)
    .Select(x => x.ModelGroup)
    .ToList();

答案 1 :(得分:0)

如果我正确地解决了问题,这将根据它们包含的内容订购商品。也应该在EF工作。

var orderItems = from item in profileModel.Groups
                 let name = item.FullName.ToLower()
                 orderby (name.Contains("ab") ? 1 : 0) + (name.Contains("cd") ? 0.1 : 0) + (name.Contains("ef") ? 0.01 : 0) descending
                 select item;

EDIT 重新阅读问题后,这可能是正确的解决方案

var orderItems = from item in profileModel.Groups
                 let name = item.FullName.ToLower()
                 let order = name.Contains("ab") ? 3 : name.Contains("cd") ? 2 : name.Contains("ef") ? 1 : 0
                 orderby order descending, item.FullName
                 select item;

答案 2 :(得分:0)

对于自定义排序,您可以为每个比较条件分配一个值,OrderByDescending将按此顺序排序。像这样......

            lstModel = profileModel.Groups.OrderByDescending(m => m.FullName.ToLower().Contains("ab") ? 3 :
            m.FullName.ToLower().Contains("cd") ? 2 :
            m.FullName.ToLower().Contains("ef") ? 1 : 0).ToList();

答案 3 :(得分:0)

如果您可能要测试更多或不同的level1值,则可能需要通用版本。

使用方便的扩展方法FirstOrDefault,该方法采用默认值返回

public static T FirstOrDefault<T>(this IEnumerable<T> src, Func<T, bool> test, T defval) => src.Where(aT => test(aT)).DefaultIfEmpty(defval).First();

您可以按顺序创建第一级值的数组,然后先按字母顺序排序,然后按字母顺序排序:

var level1 = new[] { "ab", "cd", "ef" };

var ans = groups.OrderBy(i => level1.Select((op, n) => (op, n))
                                    .FirstOrDefault(opn => i.FullName.Contains(opn.op),
                                                    (op: String.Empty, n: level1.Length)).n)
                .ThenBy(i => i.FullName);