【问题标题】:CustomSort strings by using Icomparer使用 Icomparer 自定义排序字符串
【发布时间】:2015-08-18 08:06:55
【问题描述】:

添加项目后,我必须快速对 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 中。

【问题讨论】:

    标签: c# wpf sorting mvvm icomparer


    【解决方案1】:

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

    请注意,我的IComparerIComparer&lt;Scene&gt;,而不是IComparer&lt;string&gt;

    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&lt;string&gt; 看起来非常相似:

    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 =&gt; x.SceneNumber, new SceneNumberComparer())调用

    【讨论】:

      【解决方案2】:

      也许你可以尝试如下实现 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;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-11-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-24
        • 2013-05-08
        • 1970-01-01
        • 2012-12-22
        相关资源
        最近更新 更多