简体   繁体   English

改变C#排序行为

[英]Change C# sorting behaviour

Lets say i have the strings abc_ and abc2_ . 让我们说我有字符串abc_abc2_ Now, normally when sorting i C# abc2_ would come after abc_ , leaving the result: 现在,通常排序时I C# abc2_要跟从abc_ ,留下的结果:

  1. abc_
  2. abc2_

I am using this to sort, if it matters: 如果重要的话,我用这个来排序:

     var element = from c in elements
     orderby c.elementName ascending
     select c;

How can i change this? 我怎么能改变这个? I want abc_ to come last. 我希望abc_能够到最后。 Reversing is not an option because the list is contains more than two elements. 反转不是一个选项,因为列表包含两个以上的元素。

The OrderBy method can potentially take an IComparer<T> argument. OrderBy方法可以采用IComparer<T>参数。 (I'm not sure if that overload can be used with query comprehension syntax, or if it's only available when using the fluent extension method syntax.) (我不确定该重载是否可以与查询理解语法一起使用,或者它是否仅在使用fluent扩展方法语法时可用。)

Since it's not clear exactly what your sort algorithm should involve, I'll leave implementing the required IComparer<T> as an exercise for the reader. 由于不清楚你的排序算法究竟应该涉及什么,我将继续实现所需的IComparer<T>作为读者的练习。

The simplest solution is to use the ordinal string comparer built in to the .NET Framework: 最简单的解决方案是使用.NET Framework内置的序数字符串比较器:

var element = from c in elements
    .OrderBy(c => c.elementName, StringComparer.Ordinal) 
    select c; 

No custom Comparer class needed! 无需自定义Comparer类!

If you want to underscore to play no part in the comparison, we can just make it so. 如果你想强调不参与比较,我们就可以做到这一点。 So: 所以:

class CustomComparer : Comparer<string>
    {            
        public override int Compare(string a, string b)
        {   
            //Jamiec fixed the line below.             
            return a.Replace("_", "").CompareTo(b.Replace("_", ""));
        }
    }


var customComparer = new CustomComparer();                                    
var element = elements.OrderBy(c => c.elementName, customComparer);

I'm still unsure of the actual pattern we are trying to sort on but I wrote what I thought would be a solution. 我仍然不确定我们试图解决的实际模式,但我写了我认为可以解决的问题。 I saw "_" as a kind of wildcard where "abc2_" would be a subset of "abc_". 我看到“_”是一种通配符,其中“abc2_”将是“abc_”的子集。 But from the OPs comments "bar_" < "barxyz" breaks my understanding. 但是从OP的评论“bar_”<“barxyz”打破了我的理解。 Here's my code and I can modify when I gain more clarity. 这是我的代码,当我获得更多清晰度时,我可以修改。

static void Main(string[] args)
    {
        List<Element> Elements = new List<Element>();
        Elements.Add(new Element("abc_"));
        Elements.Add(new Element("abc2_"));
        Elements.Add(new Element("aaa"));

        var max = Elements.Max(e => e.Name.Length);
        var result = Elements.OrderBy(e => e.Name, new CustomComparer(max));

        foreach (var item in result)
            Console.WriteLine(item.Name);

        Console.Read();

    }

    class Element
    {
        public string Name { get; private set; }
        public Element(string name)
        {
            this.Name = name;
        }
    }

    class CustomComparer : Comparer<string>
    {
        private const string cWildCard = "_";
        private const char cHeavyChar = 'Z';
        public int Max { get; private set; }
        public CustomComparer(int max)
        {
            this.Max = max;
        }
        public override int Compare(string a, string b)
        {
            string comp1 = string.Empty, comp2 = string.Empty;

            int index = a.IndexOf(cWildCard);
            if (index > 0)
                comp1 = a.Substring(0, index).PadRight(this.Max, cHeavyChar);
            index = b.IndexOf(cWildCard);
            if (index > 0)
                comp2 = b.Substring(0, index).PadRight(this.Max, cHeavyChar);

            int result = comp1.CompareTo(comp2);
            return result;
        }
    }

You can see I'm just weighting a word heavier from where a "_" is found. 你可以看到我只是在找到“_”的位置加权一个字。 Let me know if this is on the right track. 如果这是在正确的轨道上,请告诉我。

使用CompareOptions.Ordinal就可以了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM