组基于其中一个字段中的子字符串的对象列表

时间:2015-10-22 15:25:00

标签: c# .net linq list substring

我知道这个问题已经被问到了 Using LINQ to group a list of strings based on known substrings that they will contain

但我有一个不同的问题。

我的代码有一个对象列表

encode()

我有这些对象的列表,而Desc 3中有一个卡#substring。 (仅限某些对象)并非所有这些都有卡#。

我有一个结果对象,其中包含描述对象列表。我可以很容易地获得那些使用linq的卡#的描述列表。

public class Description
{
    public Description();

    public string Desc1 { get; set; }
    public string Desc2 { get; set; }
    public string Desc3 { get; set; }
    public DayMonthYear OriginalDate { get; set; }
    public DayMonthYear PostedDate { get; set; }
}

但接下来的部分是,desc 3字段在卡#后面还有卡#(四位数)。这些可能是不同的卡#s,可能有一个或多个。

我正在检索这个

List<Description> CardDescriptions = results.Description.Where(x => x.Desc3.Contains("CARD#")).ToList();

在linq中是否有办法获得卡片号列表#及其相关列表?

这样的东西?

List<String> cardsList = new List<String>();
string[] stringSeparators = new string[] { "CARD#" };

foreach (Description d in CardTrans)
{
    if (d.Desc3.Contains("CARD#"))
    {

        string[] text = d.Desc3.Split(stringSeparators, StringSplitOptions.None);
        if (!(cardsList.Contains(text[1])))
            cardsList.Add(text[1]);
    }
}

字符串是卡片#和我可以关联的描述对象列表吗?

我现在需要的是如何获取String卡ID列表以及与该卡相关联的整个List,这意味着Linq必须根据卡ID后的子字符串对这些对象进行分组

例如

List<Tuple<string, List<Description>>>

全部都在“1234”下,描述对象列表

Desc 3 : test test test Card#1234
Desc 3 : dsd dsftest Card#1234
Desc 3 : jjjjj iiiiii kkkk Card# 1234

全部都在“9999”下,描述对象列表

Linq可以这样做吗?或者我应该做一个foreach循环并添加新的元组,当有不同的卡子字符串#?

3 个答案:

答案 0 :(得分:2)

是的,使用linq这很容易,但是我对你的问题采取了一些自由

  1. 第3个示例包含card# 1234,其中所有其他示例中都没有额外的空格。我删除了这个空格,使问题更容易回答。
  2. 您的每个示例都会找到您希望在Card#和字符串末尾之间分组的卡号。如果总是如此,那么很好,如果不是你就需要做更多的工作。
  3. 这里的GroupBy谓词就像找到Card#的索引,提前5个字符,并读到字符串的末尾一样简单。如果字符串Card#不存在,您需要执行其他操作 - 我刚刚选择返回null

     var result = items.GroupBy(i => {
                var idx = i.Desc3.IndexOf("Card#");
                if(idx == -1)
                    return null;
    
                return i.Desc3.Substring(idx+5);
            });
    

    实例:http://rextester.com/CJD71521

答案 1 :(得分:2)

    List<String> cardsList = new List<String>();
    string[] stringSeparators = new string[] { "CARD#" };

    foreach (Description d in CardTrans)
    {
        if (d.Desc3.Contains("CARD#"))
        {

            string[] text = d.Desc3.Split(stringSeparators, StringSplitOptions.None);
            if (!(cardsList.Contains(text[1])))
                cardsList.Add(text[1]);
        }
    }

可以像这样重写:

var cardsList=CardTrans
  .Where(ct=>ct.Desc3.Contains("CARD#"))
  .Select(ct=>ct.Desc3.Split(stringSeparators,StringSplitOptions.None)[1])
  .Disinct();

如果您希望将它们分组,那么:

var cardsList=CardTrans
  .Where(ct=>ct.Desc3.Contains("CARD#"))
  .GroupBy(key=>key.Desc3.Split(stringSeparators,StringSplitOptions.None)[1]);

将产生IGrouping<string,Description>。如果你想要一个元组,我想这会做到:

var cardsList=CardTrans
  .Where(ct=>ct.Desc3.Contains("CARD#"))
  .GroupBy(key=>key.Desc3.Split(stringSeparators,StringSplitOptions.None)[1])
  .Select(x=>Tuple.Create<string,IEnumerable<Description>>(x.Key,x));

测试:

public class Program
{
   public static void Main(string[] args)
   {
        string[] stringSeparators = new string[] { "CARD#" };
       var CardTrans = new List<Description>()
       {
           new Description(){Desc3="test test test CARD#1234"},
           new Description(){Desc3="dsd dsftest CARD#1234"},
           new Description(){Desc3="jjjjj iiiiii kkkk CARD#1234"},
           new Description(){Desc3="ujeuejduejtest test CARD#9999"},
           new Description(){Desc3="2323fseff dsftest CARD#9999"},
           new Description(){Desc3="sdfsd fsdsdf kkkk CARD#9999"}
       };

        var cardsList=CardTrans
            .Where(ct=>ct.Desc3.Contains("CARD#"))
            .GroupBy(key=>key.Desc3.Split(stringSeparators,StringSplitOptions.None)[1])
            .Select(x=>Tuple.Create<string,IEnumerable<Description>>(x.Key,x));
        cardsList.Dump();
   }
}

public class Description
{
   public Description(){}

   public string Desc1 { get; set; }
   public string Desc2 { get; set; }
   public string Desc3 { get; set; }
   public DayMonthYear OriginalDate { get; set; }
   public DayMonthYear PostedDate { get; set; }
}

public class DayMonthYear{}

输出:

enter image description here

答案 2 :(得分:1)

您可以将Regex用于此目的。

List<Description> list = new List<Description>();
// ...
var result =
     list.GroupBy(x => Regex.Match(x.Desc3, "CARD# *(\\d{4,4})", RegexOptions.IgnoreCase).Groups[1].Value)
         .Select(x => Tuple.Create(x.Key, x.ToList()))
         .ToList();

result.RemoveAll(x => x.Item1 == ""); // exclude items without card.

这是测试。

List<Description> list = new List<Description>
{
    new Description {Desc1 = "No Card" ,Desc3 = "No Card"},
    new Description {Desc1 = "Des A" ,Desc3 = "ujeuejduejtest test Card#9999"},
    new Description {Desc1 = "Des B" ,Desc3 = " test test test Card#1234"},
    new Description {Desc1 = "Des C" ,Desc3 = "2323fseff dsftest Card#9999"},
    new Description {Desc1 = "Des D" ,Desc3 = " jjjjj iiiiii kkkk Card# 1234"},
};

var result = ...;            

foreach (var tuple in result)
{
    Console.Write("CARD#{0} : ",tuple.Item1);
    foreach (var description in tuple.Item2)
    {
        Console.Write(description.Desc1 + ", ");
    }
    Console.WriteLine();
}

输出:

Card#9999 : Des A, Des C,
Card#1234 : Des B, Des D,