【问题标题】:Filter List<string> based on only a Substring过滤 List<string> 仅基于一个子字符串
【发布时间】:2018-08-14 20:36:34
【问题描述】:

我有一个 SKU(产品编号)列表,需要根据非常具体的标准对其进行排序。

SKU 列表,例如:

List<string> skuList = new List<string>()
{
    "SKU001040AA",
    "SKU003010DED",
    "SKU002010VEVW",
    "SKU003040EEGE",
    "SKU001020GEF"
};

每个 SKU 的结构如下:

  • 前三个字符是填充符
  • 第 4-6 个字符是指 SKU 所属的组
  • 第 7-9 个字符是指 SKU 在其各自组中的优先级
  • 剩下的第 10 个等字符是填充符

因此,列表中的第一个 SKU 属于组 001,优先级为 040。数值越小优先级越高。在这种情况下,030 的优先级高于 040。我的目标是过滤列表,以便仅保留各自组中优先级最高的 SKU。使用上述列表作为参考,过滤后的列表将包含“SKU003010DED”、“SKU002010VEVW”和“SKU001020GEF”。过滤后的列表不需要排序。它最终会被打包成一个 JSON 对象并被发送出去。

我尝试了几种不同的方法,其中几种似乎效率很低。我突然想到,我可以使用 SKU 的当前格式轻松订购列表。之后,我认为可以使用 Contains() 方法检查子字符串是否存在,但自然只适用于列表中的完整字符串...

skuList = skuList.OrderBy(x => x).ToList();
List<string> skuListFiltered = new List<string>();
foreach (var sku in skuList)
{
    //Unsure of the best approach to view substrings of skuList
    if (!skuList.Contains(sku.Substring(3,3)))
    {
        skuListFiltered.Add(sku);
    }
}

有没有办法以这种方式过滤这个列表,或者我应该尝试一种完全不同的方法?

【问题讨论】:

    标签: c# string list linq filtering


    【解决方案1】:

    我强烈建议您开设这样的课程。这里的关键是隐式转换运算符;此类的实例可以分配给字符串或从字符串分配,但您也可以使用它的属性来解析它。

    class Sku
    {
        public string Prefix { get; set; }
        public string Group  { get; set; }
        public string Priority { get; set; }
        public string Suffix { get; set; }
    
        public override string ToString()
        {
            return string.Format("{0}{1}{2}{3}", Prefix, Group, Priority, Suffix);
        }
    
        static public implicit operator Sku(string input)
        {
            return new Sku
            {
                Prefix = input.Substring(0,3),
                Group = input.Substring(3,3),
                Priority = input.Substring(6,3),
                Suffix = input.Substring(9)
            };
        }
    
        static public implicit operator string(Sku input)
        {
            return input.ToString();
        }
    }
    

    现在 LINQ 很简单:

    public class Program
    {
        public static void Main()
        {
    
            List<Sku> skuList = new List<Sku>()  //Notice this is strongly typed as <Sku> now
            {
                "SKU001040AA",
                "SKU003010DED",
                "SKU002010VEVW",
                "SKU003040EEGE",
                "SKU001020GEF"
            };
    
            var results = skuList
                .Select( s => s.Group )
                .Distinct()
                .Select
                ( 
                    g => skuList.Where
                    ( 
                        s => s.Group == g
                    )
                    .OrderBy
                    (
                        s => s.Priority
                    )
                    .First()
                );
    
            foreach (var r in results)
                Console.WriteLine(r);                                                                        
    
        }   
    }
    

    输出:

    SKU001020GEF
    SKU003010DED
    SKU002010VEVW
    

    Code on DotNetFiddle

    【讨论】:

    • 我喜欢这个。只是一个问题,在隐式转换运算符代码中处理错误格式的字符串的最佳方法是什么。如果字符串太短,子字符串可能会引发异常。什么是反馈出来的最好方法,只是让它把参数抛出范围异常感觉有点奇怪。是否只是检查字符串长度/捕获异常并抛出 InvalidCastException 的情况?
    • 如果无效 SKU 是预期和常见的,您仍然可以允许强制转换但返回一个空的 SKU 对象,可能将 IsValid 属性设置为 false,因此您可以在代码中检查它。如果无效 SKU 很少见且异常,请引发异常。另一种选择是允许强制转换返回 null;调用者在做任何其他事情之前需要做一个空检查。
    【解决方案2】:

    处理过程如下:

    • 识别列表中的 SKU 组
    • 将每个 SKU 附加到其各自的组
    • 按优先级对每个组中的 SKU 进行排序
    • 在每组中选择最上面的项目
    • 从分组结果中创建一个平面列表

    这是使用 LINQ 的方法:

    var topPriority = skuList
        .GroupBy(sku => sku.Substring(3, 3))
        .Select(g => g.OrderBy(sku => sku.Substring(6, 3)).First())
        .ToList();
    

    请注意,由于优先级是零填充的,因此它们的长度相同,均为 3 个字符。因此,字典顺序与数字顺序相同。

    【讨论】:

    • 不应该是升序吗?否则 +1,我自己得到了完全相同的结果代码。
    • @Lucas 对,OP 说“较低的数字--> 较高的优先级”。谢谢!
    • 这非常简单,正是我想要的。非常感谢您详细说明每一步。它有助于我理解 LINQ(无论如何我真的需要更好地学习)。
    猜你喜欢
    • 1970-01-01
    • 2013-03-30
    • 1970-01-01
    • 2011-09-26
    • 2023-04-06
    • 1970-01-01
    • 2019-12-25
    • 1970-01-01
    • 2012-04-06
    相关资源
    最近更新 更多