Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用自己的IComparer<;T>;与Linq OrderBy合作_C#_Linq_Sql Order By_Icomparer - Fatal编程技术网

C# 使用自己的IComparer<;T>;与Linq OrderBy合作

C# 使用自己的IComparer<;T>;与Linq OrderBy合作,c#,linq,sql-order-by,icomparer,C#,Linq,Sql Order By,Icomparer,我有一个通用的 List<MyClass> 它支持使用linq进行排序: protected override void ApplySortCore( PropertyDescriptor property, ListSortDirection direction) { _sortProperty = property; _sortDirection = direction; var items = this.Items;

我有一个通用的

List<MyClass>
它支持使用linq进行排序:

protected override void ApplySortCore(
           PropertyDescriptor property, ListSortDirection direction)
{

    _sortProperty = property;
    _sortDirection = direction;

    var items = this.Items;

    switch (direction)
    {
        case ListSortDirection.Ascending:
            items = items.OrderByDescending(x => property.GetValue(x)).ToList();
            break;
        case ListSortDirection.Descending:
            items = items.OrderByDescending(x => property.GetValue(x)).ToList();
            break;
    }

    this.Items = items;

}
但是,默认比较器按如下方式排序:

public class MyComparer : IComparer<Object>
{

    public int Compare(Object stringA, Object stringB)
    {
        String[] valueA = stringA.ToString().Split('/');
        String[] valueB = stringB.ToString().Split('/');

        if(valueA .Length != 2 || valueB .Length != 2)
             return String.Compare(stringA.ToString(), stringB.ToString());

        if (valueA[0] == valueB[0]) 
        {
          return String.Compare(valueA[1], valueB[1]);
        }
        else
        {
          return String.Compare(valueA[0], valueB[0]);
        }

    }

}
public class MyComparer : IComparer<string>
{

    public int Compare(string stringA, string stringB)
    {
        string small = stringA;
        string big = stringB;
        if (stringA.Length > stringB.Length)
        {
            small = stringB;
            big = stringA;
        }
        else if (stringA.Length < stringB.Length)
        {
            small = stringA;
            big = stringB;
        }
        for (int j = 0; j < small.Length; j++)
        {
            if (Convert.ToInt32(small[j]) > Convert.ToInt32(big[j])) return -1;
            if (Convert.ToInt32(small[j]) < Convert.ToInt32(big[j])) return 1;
        }

        //big is indeed bigger
        if (big.Length > small.Length) return 1;

        //finally they are smae
        return 0;
    }
}
200906/1
200906/10
200906/11
200906/12
200906/2

在这种情况下,这是令人讨厌的

现在我想用我自己的
IComparer
与此进行比较。看起来是这样的:

public class MyComparer : IComparer<Object>
{

    public int Compare(Object stringA, Object stringB)
    {
        String[] valueA = stringA.ToString().Split('/');
        String[] valueB = stringB.ToString().Split('/');

        if(valueA .Length != 2 || valueB .Length != 2)
             return String.Compare(stringA.ToString(), stringB.ToString());

        if (valueA[0] == valueB[0]) 
        {
          return String.Compare(valueA[1], valueB[1]);
        }
        else
        {
          return String.Compare(valueA[0], valueB[0]);
        }

    }

}
public class MyComparer : IComparer<string>
{

    public int Compare(string stringA, string stringB)
    {
        string small = stringA;
        string big = stringB;
        if (stringA.Length > stringB.Length)
        {
            small = stringB;
            big = stringA;
        }
        else if (stringA.Length < stringB.Length)
        {
            small = stringA;
            big = stringB;
        }
        for (int j = 0; j < small.Length; j++)
        {
            if (Convert.ToInt32(small[j]) > Convert.ToInt32(big[j])) return -1;
            if (Convert.ToInt32(small[j]) < Convert.ToInt32(big[j])) return 1;
        }

        //big is indeed bigger
        if (big.Length > small.Length) return 1;

        //finally they are smae
        return 0;
    }
}
当我调试代码时,我看到
MyComparer.Compare(object,object)
被多次调用,并为Compare方法返回正确的值(-1,0,1)


但我的列表仍然是按“错误”的方式排序的。我错过什么了吗?我不知道。

我觉得你的比较器错了。您仍然只是按默认文本顺序排序。当然,您希望解析这两个数字并基于此进行排序:

public int Compare(Object stringA, Object stringB)
{
    string[] valueA = stringA.ToString().Split('/');
    string[] valueB = stringB.ToString().Split('/');

    if (valueA.Length != 2 || valueB.Length != 2)
    {
        stringA.ToString().CompareTo(stringB.ToString());
    }

    // Note: do error checking and consider i18n issues too :)
    if (valueA[0] == valueB[0]) 
    {
        return int.Parse(valueA[1]).CompareTo(int.Parse(valueB[1]));
    }
    else
    {
        return int.Parse(valueA[0]).CompareTo(int.Parse(valueB[0]));
    }
}
(请注意,这与您的问题不符,您的问题指出您已经调试并验证了Compare是否返回了正确的值,但我怀疑这方面存在人为错误。)

此外,Sven的右键更改
项的值根本不会更改绑定列表。您应该添加:

this.Items = items;

在方法的底部。

排序列表仅绑定到局部变量项,而不绑定到绑定列表的items属性,因此它保持未排序状态


[编辑]基本上,您只是在丢弃排序工作的结果;-)

我遇到了一般自然排序的问题,并将解决方案写在了这里:

公共类NaturalSortComparer:IComparer,IDisposable
{
私人住宅;
公共自然排序比较器(bool inAscendingOrder=true)
{
this.isAscending=inAscendingOrder;
}
#地区I比较成员
公共整数比较(字符串x、字符串y)
{
抛出新的NotImplementedException();
}
#端区
#地区I比较成员
int IComparer.Compare(字符串x、字符串y)
{
如果(x==y)
返回0;
字符串[]x1,y1;
如果(!table.TryGetValue(x,out x1))
{
x1=Regex.Split(x.Replace(“,”),“([0-9]+)”);
表.增加(x,x1);
}
如果(!table.TryGetValue(y,out y1))
{
y1=正则表达式拆分(y.Replace(“,”),“([0-9]+)”);
表.添加(y,y1);
}
int returnVal;
对于(int i=0;ix1.长度)
{
returnVal=1;
}
否则,如果(x1.长度>y1.长度)
{ 
returnVal=-1;
}
其他的
{
returnVal=0;
}
return isascing?returnVal:-returnVal;
}
私有静态int-PartCompare(字符串左、字符串右)
{
int x,y;
如果(!int.TryParse(左,外x))
返回左侧。比较(右侧);
如果(!int.TryParse(右,out y))
返回左侧。比较(右侧);
返回x.CompareTo(y);
}
#端区
私有字典表=新字典();
公共空间处置()
{
表1.Clear();
table=null;
}
}

您可以使用Alphanum算法:

  (...)
    items.OrderBy(x => property.GetValue(x), new AlphanumComparator())
  (...)

/*
*Alphanum算法是一种改进的字符串排序算法
*包含数字。而不是像这样按ASCII顺序对数字进行排序
*作为一种标准排序,该算法按数字顺序对数字进行排序。
*
*Alphanum算法在http://www.DaveKoelle.com
*
*基于Dave Koelle的Alphanum算法的Java实现。
*乔纳森·拉克伍德撰稿
*
*由Dominik Hurnaus改编为
*-正确排序一个单词以另一个单词开头的单词
*-性能稍好
*
*根据麻省理工学院许可证发布-https://opensource.org/licenses/MIT
*
*特此免费向获得许可的任何人授予许可
*本软件及相关文档文件(“软件”)的副本,
*不受限制地处理软件,包括但不限于
*使用、复制、修改、合并、发布、分发、再许可、,
*和/或出售软件副本,并允许
*为此提供的软件应符合以下条件:
*
*应包括上述版权声明和本许可声明
*在软件的所有副本或主要部分。
*
*软件按“原样”提供,无任何形式的担保,
*明示或暗示,包括但不限于
*适销性、特定用途适用性和非侵权性。
*在任何情况下,作者或版权持有人均不对任何索赔负责,
*损害赔偿或其他责任,无论是在合同诉讼、侵权诉讼或
*否则,由本软件或
*在软件中使用或进行其他交易。
*
*/
使用制度;
使用系统集合;
使用系统文本;
/*
*请与上的最新Java版本进行比较http://www.DaveKoelle.com
*查看最新的修改
*/
名称空间字母计算器
{
公共类字母计算器:IComparer
{
私有枚举ChunkType{字母数字,数字};
私有布尔InChunk(char ch,char otherCh)
{
ChunkType类型=ChunkType.字母数字;
如果(字符为数字(其他字符))
{
type=ChunkType.Numeric;
}
if((type==ChunkType.Alphanumeric&&char.IsDigit(ch))
||(type==ChunkType.Numeric&&!char.IsDigit(ch)))
{
返回false;
}
返回true;
}
公共整数比较(对象x、对象y)
{
字符串s1=x作为字符串;
字符串s2=y
/*
 * The Alphanum Algorithm is an improved sorting algorithm for strings
 * containing numbers.  Instead of sorting numbers in ASCII order like
 * a standard sort, this algorithm sorts numbers in numeric order.
 *
 * The Alphanum Algorithm is discussed at http://www.DaveKoelle.com
 *
 * Based on the Java implementation of Dave Koelle's Alphanum algorithm.
 * Contributed by Jonathan Ruckwood <jonathan.ruckwood@gmail.com>
 *
 * Adapted by Dominik Hurnaus <dominik.hurnaus@gmail.com> to
 *   - correctly sort words where one word starts with another word
 *   - have slightly better performance
 *
 * Released under the MIT License - https://opensource.org/licenses/MIT
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */
using System;
using System.Collections;
using System.Text;

/*
 * Please compare against the latest Java version at http://www.DaveKoelle.com
 * to see the most recent modifications
 */
namespace AlphanumComparator
{
    public class AlphanumComparator : IComparer
    {
        private enum ChunkType {Alphanumeric, Numeric};
        private bool InChunk(char ch, char otherCh)
        {
            ChunkType type = ChunkType.Alphanumeric;

            if (char.IsDigit(otherCh))
            {
                type = ChunkType.Numeric;
            }

            if ((type == ChunkType.Alphanumeric && char.IsDigit(ch))
                || (type == ChunkType.Numeric && !char.IsDigit(ch)))
            {
                return false;
            }

            return true;
        }

        public int Compare(object x, object y)
        {
            String s1 = x as string;
            String s2 = y as string;
            if (s1 == null || s2 == null)
            {
                return 0;
            }

            int thisMarker = 0, thisNumericChunk = 0;
            int thatMarker = 0, thatNumericChunk = 0;

            while ((thisMarker < s1.Length) || (thatMarker < s2.Length))
            {
                if (thisMarker >= s1.Length)
                {
                    return -1;
                }
                else if (thatMarker >= s2.Length)
                {
                    return 1;
                }
                char thisCh = s1[thisMarker];
                char thatCh = s2[thatMarker];

                StringBuilder thisChunk = new StringBuilder();
                StringBuilder thatChunk = new StringBuilder();

                while ((thisMarker < s1.Length) && (thisChunk.Length==0 ||InChunk(thisCh, thisChunk[0])))
                {
                    thisChunk.Append(thisCh);
                    thisMarker++;

                    if (thisMarker < s1.Length)
                    {
                        thisCh = s1[thisMarker];
                    }
                }

                while ((thatMarker < s2.Length) && (thatChunk.Length==0 ||InChunk(thatCh, thatChunk[0])))
                {
                    thatChunk.Append(thatCh);
                    thatMarker++;

                    if (thatMarker < s2.Length)
                    {
                        thatCh = s2[thatMarker];
                    }
                }

                int result = 0;
                // If both chunks contain numeric characters, sort them numerically
                if (char.IsDigit(thisChunk[0]) && char.IsDigit(thatChunk[0]))
                {
                    thisNumericChunk = Convert.ToInt32(thisChunk.ToString());
                    thatNumericChunk = Convert.ToInt32(thatChunk.ToString());

                    if (thisNumericChunk < thatNumericChunk)
                    {
                        result = -1;
                    }

                    if (thisNumericChunk > thatNumericChunk)
                    {
                        result = 1;
                    }
                }
                else
                {
                    result = thisChunk.ToString().CompareTo(thatChunk.ToString());
                }

                if (result != 0)
                {
                    return result;
                }
            }

            return 0;
        }
    }
}
public class MyComparer : IComparer<string>
{

    public int Compare(string stringA, string stringB)
    {
        string small = stringA;
        string big = stringB;
        if (stringA.Length > stringB.Length)
        {
            small = stringB;
            big = stringA;
        }
        else if (stringA.Length < stringB.Length)
        {
            small = stringA;
            big = stringB;
        }
        for (int j = 0; j < small.Length; j++)
        {
            if (Convert.ToInt32(small[j]) > Convert.ToInt32(big[j])) return -1;
            if (Convert.ToInt32(small[j]) < Convert.ToInt32(big[j])) return 1;
        }

        //big is indeed bigger
        if (big.Length > small.Length) return 1;

        //finally they are smae
        return 0;
    }
}
string[] inputStrings = {"_abc*&","#almnp","abc" };
//string[] inputStrings = { "#", "_", "_a", "@", "_" };
MyComparer computer = new MyComparer();
var kola = inputStrings.OrderBy(x => x, new MyComparer()).ToArray();
    Array.Sort(inputStrings, StringComparer.Ordinal);