仅基于子字符串过滤列表<string>

时间:2018-03-06 21:18:42

标签: c# string list linq filtering

我有一份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);
    }
}

有没有办法以这种方式过滤此列表,还是应该尝试完全不同的方法?

2 个答案:

答案 0 :(得分:3)

处理过程如下:

  • 识别列表中的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 :(得分:3)

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

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