【问题标题】:List<string> complex sortingList<string> 复杂排序
【发布时间】:2012-11-29 05:44:49
【问题描述】:

我有一个List&lt;string&gt; 的尺码,比如 XS、S、M、L、XL、XXL、UK 10、UK 12 等

我想要的是强制顺序为上述顺序,无论列表中项目的顺序如何,我认为我需要一个 IComparable 运算符但不确定。

理想情况下,我希望有另一个具有正确顺序的列表,它可以引用它在列表中的“位置”并重新排序,如果它不存在,它将默认为 A-Z

【问题讨论】:

  • @Tigran 我猜?他想使用自定义IComparer&lt;T&gt; 对内容进行排序。对于第二部分? SortedDictionary 可能会起作用。
  • @Tigran 基本上我有一个 List 包含: XXXL、S、M、L 以任何顺序我需要按照我的状态对它们进行排序(也许在另一个列表中以正确的顺序)所以结果是:S,M,L,XXXL
  • 您可能需要考虑创建一个枚举并转换值。

标签: c# linq sorting lambda arraylist


【解决方案1】:

按照您希望它们的顺序创建一个尺寸数组,然后按尺寸在该数组中的位置对衬衫进行排序:

string[] sizes = new [] {"XS", "S", "M", "L", "XL", "XXL", "UK 10", "UK 12"};

var shirtsInOrder = shirts
                        .OrderBy(s=>sizes.Contains(s) ? "0" : "1")  // put unmatched sizes at the end
                        .ThenBy(s=>Array.IndexOf(sizes,s))  // sort matches by size
                        .ThenBy(s=>s); // sort rest A-Z

【讨论】:

  • using a dictionary is preferable 对数组执行线性搜索。
  • 我错过了 "如果它不存在,它将默认为 A-Z"
  • 谢谢,第 2 行如何与第 1 行协同工作?也不确定 s.Size 来自哪里?
  • 我提供了一个示例,假设您有一个具有 Size 属性的 Shirt 类 - 它可能不适合您的特定用途,只是一个示例。
  • 啊,是的,我明白了。不,目前我只有一个 List 而不是一个类,可能需要在我的代码中转换它,除非有一个简单的解决方案?
【解决方案2】:
var order = new string[] { "XS", "S", "M", "L", "XL", "XXL", "UK10", "UK12" };

var orderDict = order.Select((c, i) => new { sze = c, ord = i })
            .ToDictionary(o => o.sze, o => o.ord);

var list = new List<string> { "S", "L", "XL", "L", "L", "XS", "XL" };
var result = list.OrderBy(item => orderDict[item]);

【讨论】:

  • 这里我也错过了 "如果它不存在,它将默认为 A-Z"
  • 谢谢,如果字典中不存在该值,我需要它按 a-z 排序,如果它不存在,它就会失败..
【解决方案3】:

你可以直接使用OrderByDescending + ThenByDescending

sizes.OrderByDescending(s => s == "XS")
     .ThenByDescending( s => s == "S")
     .ThenByDescending( s => s == "M")
     .ThenByDescending( s => s == "L")
     .ThenByDescending( s => s == "XL")
     .ThenByDescending( s => s == "XXL")
     .ThenByDescending( s => s == "UK 10")
     .ThenByDescending( s => s == "UK 12")
     .ThenBy(s => s);

我使用...Descending,因为true 类似于1,而false 是0。

【讨论】:

  • 类似地,当我想对uints 的列表进行排序时,我会使用var sorted = myUints.OrderByDescending(mu =&gt; mu == 0); for (uint u = 1; u &lt; 1000; u++) sorted = sorted.ThenByDescending(s =&gt; s == u); sorted = sorted.ThenBy(s =&gt; s);
  • 谢谢蒂姆,它订购的是 S、M、L 等,但不是 UK 6、UK 8 等,可能是因为数字吗?
  • @dhardy:你想如何订购英国号码?我以为只有两个(UK 10 和 UK 12)。
  • 这是我需要的顺序:“15”、“15.5”、“16”、“16,5”、“17”、“17.5”、“18”、“18.5”、“ 19”、“英国 6”、“英国 8”、“英国 10”、“英国 12”、“英国 14”、“英国 16”、“XS”、“S”、“M”、“L”、“ XL”、“XXL”谢谢,戴夫
【解决方案4】:

你也可以这样做:

public class ShirtComparer : IComparer<string>
{
    private static readonly string[] Order = new[] { "XS", "S", "M", "L", "XL", "XXL", "UK10", "UK12" };

    public int Compare(string x, string y)
    {
        var xIndex = Array.IndexOf(Order, x);
        var yIndex = Array.IndexOf(Order, y);

        if (xIndex == -1 || yIndex == -1) 
            return string.Compare(x, y, StringComparison.Ordinal);

        return xIndex - yIndex;
    }
}

用法:

var list = new List<string> { "S", "L", "XL", "L", "L", "XS", "XL", "XXXL", "XMLS", "XXL", "AM19" };
var result = list.OrderBy(size => size, new ShirtComparer());

对于不在列表中的值,它也应该默认为 A-Z...

【讨论】:

    【解决方案5】:

    您还可以创建其他列表,并使用委托与排序一起使用,如果 size1 的索引 > size2 的索引,则返回。

    【讨论】:

      猜你喜欢
      • 2016-11-25
      • 2018-01-19
      • 2020-07-10
      • 2020-02-06
      • 1970-01-01
      • 1970-01-01
      • 2015-02-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多