使用Icomparer在大写之前排序小写字母

时间:2017-07-24 05:51:48

标签: c# wpf sorting icomparer

我有一个ListCollectionView,它包含一组场景对象,我需要按场景Number(Scene.SceneNumber)对它进行排序,这是一个包含数字和字母的字符串,我需要按照特定的顺序对其进行排序。首先是数字,然后是字母,首先是小写字母,然后是大写字母。

列表需要如下所示:

1
1pt1
1pt2
1A
1Apt1
2
2pt1
2Apt1
3
...

这是我到目前为止所做的:

public class SceneComparer : IComparer
{
    private readonly Regex sceneRegEx = new Regex(@"(\d+)(\w+)?", RegexOptions.Compiled);

    public int Compare(object x, object y)
    {
        Scene sceneX = x as Scene;
        Scene sceneY = y as Scene;

        var firstSceneMatches = this.sceneRegEx.Matches(sceneX.SceneNumber);
        var secondSceneMatches = this.sceneRegEx.Matches(sceneY.SceneNumber);

        var matchesCount = Math.Min(firstSceneMatches.Count, secondSceneMatches.Count);
        for (var i = 0; i < matchesCount; i++)
        {
            var firstSceneMatch = firstSceneMatches[i];
            var secondSceneMatch = secondSceneMatches[i];

            var firstSceneNumeric = Convert.ToInt32(firstSceneMatch.Groups[1].Value);
            var secondSceneNumeric = Convert.ToInt32(secondSceneMatch.Groups[1].Value);
            if (firstSceneNumeric != secondSceneNumeric)
            {
                return firstSceneNumeric - secondSceneNumeric;
            }

            var firstSceneAlpha = firstSceneMatch.Groups[2].Value;
            var secondSceneAlpha = secondSceneMatch.Groups[2].Value;
            if (firstSceneAlpha != secondSceneAlpha)
            {
                return string.CompareOrdinal(firstSceneAlpha, secondSceneAlpha);
            }
        }
        return firstSceneMatches.Count - secondSceneMatches.Count;
     }
}

这导致以下列表

1
1A
1Apt1
1pt1
1pt2
2
2Apt1
2pt1
...

但我需要大写字母前面的小写字母。我该怎么做?

1 个答案:

答案 0 :(得分:-1)

//Usage: 
var sortedStrs = strings.OrderBy(s => s, new CollectionComparer<char>(CompareChar)).ToList();

private static int CompareChar(char c1, char c2)
{
    if (char.IsNumber(c1) || char.IsNumber(c2))
    {
        return c1 - c2;
    }

    var s1 = c1.ToString();
    var s2 = c2.ToString();
    var isLowerCaseS1 = s1 == s1.ToLower();
    var isLowerCaseS2 = s2 == s2.ToLower();

    if (isLowerCaseS1 && isLowerCaseS2 || !isLowerCaseS1 && !isLowerCaseS2)
    {
        return c1.CompareTo(c2);
    }

    return isLowerCaseS1 ? -1 : 1;
}


public class CollectionComparer<T> : IComparer<IEnumerable<T>>
{
    private readonly Func<T, T, int> _comparisonFunc;

    public CollectionComparer(Func<T, T, int> comparisonFunc)
    {
        _comparisonFunc = comparisonFunc;
    }

    public int Compare(IEnumerable<T> c1, IEnumerable<T> c2)
    {
        //Ensure.Argument.NotNull(c1);
        //Ensure.Argument.NotNull(c2);

        var collection2 = c2?.ToList() ?? new List<T>();
        var collection1 = c1?.ToList() ?? new List<T>();

        var result = collection1.Select(
            (c, ind) => collection2.Count() > ind ? _comparisonFunc(c, collection2.ElementAt(ind)) : 1)
            .FirstOrDefault(e => e != 0);

        return result != 0 ? result : (collection2.Count > collection1.Count() ? -1 : 0);
    }
}