使用Icomparer的CustomSort字符串

时间:2015-08-18 08:06:55

标签: c# wpf sorting mvvm icomparer

添加Item后,我必须快速对ListCollectionView中的项进行排序。 我尝试使用CustomSort并创建自己的IComparer

ListCollectionView中的项目是Scene类型,我想根据SceneNumber对项目进行排序,SceneNumber是Scene的一个属性,因为它包含数字后跟字母。

我想排序

1
10
15A
2
30B
4B
4A

1
2
4A
4B
10
15A
30

这是我目前在Icomparer中所拥有的内容

public class SortScenes : IComparer<string>
{
    public int Compare(object x, object y)
    {

        if (((Scene)x).SceneNumber > ((Scene)y).SceneNumber)
        {
            return 1;
        }
        return -1;
    }
}

如何通过使用字符串来完成这项工作。

我想实现以下

var nums = "0123456789".ToCharArray();
SceneList.OrderBy(x => x.SceneNumber.LastIndexOfAny(nums)).ThenBy(x => x.SceneNumber))

但是在IComparer中。

2 个答案:

答案 0 :(得分:0)

我会考虑将Scene.SceneNumber拆分为例如数字“主场景”和阿尔法“子场景”。鉴于您的场景声明,我使用RegEx将SceneNumber分割为数字和可选的alpha部分。

请注意,我的IComparerIComparer<Scene>,而不是IComparer<string>

namespace SceneSorter
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text.RegularExpressions;

    class Program
    {
        static void Main(string[] args)
        {
            var sceneList = new List<Scene>
                                {
                                    new Scene { SceneNumber = "1" },
                                    new Scene { SceneNumber = "10" },
                                    new Scene { SceneNumber = "15A" },
                                    new Scene { SceneNumber = "2" },
                                    new Scene { SceneNumber = "30B" },
                                    new Scene { SceneNumber = "4B" },
                                    new Scene { SceneNumber = "4A" }
                                };

            foreach (var scene in sceneList.OrderBy(x => x, new SceneComparer()))
            {
                Console.WriteLine(scene.SceneNumber);
            }
        }
    }

    public class Scene
    {
        // TODO: Consider splitting SceneNumber into a e.g. a numeric "main scene" and an alpha "sub scene".
        public string SceneNumber { get; set; }
    }

    public class SceneComparer : IComparer<Scene>
    {
        // Assumes that a scene is either numeric, or numeric + alpha.
        private readonly Regex sceneRegEx = new Regex(@"(\d*)(\w*)", RegexOptions.Compiled);

        public int Compare(Scene x, Scene y)
        {
            var firstSceneMatch = this.sceneRegEx.Match(x.SceneNumber);

            var firstSceneNumeric = Convert.ToInt32(firstSceneMatch.Groups[1].Value);
            var firstSceneAlpha = firstSceneMatch.Groups[2].Value;

            var secondSceneMatch = this.sceneRegEx.Match(y.SceneNumber);

            var secondSceneNumeric = Convert.ToInt32(secondSceneMatch.Groups[1].Value);
            var secondSceneAlpha = secondSceneMatch.Groups[2].Value;

            if (firstSceneNumeric < secondSceneNumeric)
            {
                return -1;
            }

            if (firstSceneNumeric > secondSceneNumeric)
            {
                return 1;
            }

            return string.CompareOrdinal(firstSceneAlpha, secondSceneAlpha);
        }
    }
}
1
2
4A
4B
10
15A
30B
Press any key to continue . . .

IComparer<string>看起来非常相似:

public class SceneNumberComparer : IComparer<string>
{
    // Assumes that a scene is either numeric, or numeric + alpha.
    private readonly Regex sceneRegEx = new Regex(@"(\d*)(\w*)", RegexOptions.Compiled);

    public int Compare(string x, string y)
    {
        var firstSceneMatch = this.sceneRegEx.Match(x);

        var firstSceneNumeric = Convert.ToInt32(firstSceneMatch.Groups[1].Value);
        var firstSceneAlpha = firstSceneMatch.Groups[2].Value;

        var secondSceneMatch = this.sceneRegEx.Match(y);

        var secondSceneNumeric = Convert.ToInt32(secondSceneMatch.Groups[1].Value);
        var secondSceneAlpha = secondSceneMatch.Groups[2].Value;

        if (firstSceneNumeric < secondSceneNumeric)
        {
            return -1;
        }

        if (firstSceneNumeric > secondSceneNumeric)
        {
            return 1;
        }

        return string.CompareOrdinal(firstSceneAlpha, secondSceneAlpha);
    }
}

...由.OrderBy(x => x.SceneNumber, new SceneNumberComparer())

调用

答案 1 :(得分:0)

也许你可以尝试按如下方式实现Compare方法:

public static char[] nums = "0123456789".ToCharArray();

public static int Compare(string x, string y)
{
    if (x.LastIndexOfAny(nums) > y.LastIndexOfAny(nums))
    {
        return 1;
    }
    if (x.LastIndexOfAny(nums) == y.LastIndexOfAny(nums))
    {
        return x.CompareTo(y);
    }
    return -1;
}