【问题标题】:How to combine two list according to date如何根据日期组合两个列表
【发布时间】:2019-02-15 12:03:24
【问题描述】:

我有两个字符串列表,第一个列表包含每个元素对应的第二个列表的 ID。列表的定义,

IdsList ["Id1","Id2"]
ShippingsNoList ["n1,n2..","t1,t2"] 

表示n1,n2->Id1, t1,t2->Id2

IdsList 格式 -> A-date-B ShippingNumbersList 格式-> number1,number2,etc.

我的目的是结合两个列表并将结果作为字符串返回。如果我发现 ShippingNumber 等于另一个 ShippingNumber 并且它们的 Id 日期 也应该匹配,那么我应该使用 Shipping Number 和相关 ID。一个运输编号可能已经分配了多个相同日期的 ID。 示例:

IdsList=["A-28.03.18-B", 
         "S-17.05.18-G", 
         "L-17.05.18-P",
         "M-28.03.18-T",
         "B-17.05.18-U"]

ShippingNumbersList=["100,200,300", 
                      "100,900", 
                      "200,300,100",
                      "100,900,300",
                      "100,300"]

预期结果:

100-> A-28.03.18-B,M-28.03.18-T
300-> A-28.03.18-B,M-28.03.18-T
100-> S-17.05.18-G,L-17.05.18-P,B-17.05.18-U
300-> L-17.05.18-P, B-17.05.18-U

【问题讨论】:

  • 为什么Expected Result 不包含200900 的条目?
  • 很难理解您的预期结果。您应该简化您的帖子以获得我们的快速帮助
  • 因为 200 第一行的 ID 是 A-28.03.18-B 而第三行是 L-17.05.18-P 。好的,发货编号匹配,但 ID 的日期不匹配 - 28.03.18 != 17.05.18 。同样的事情对900 也有效。
  • 谢谢,澄清一下 - 更新了我的答案,应该是你要找的。​​span>
  • 我不知道你的数据是从哪里来的,但是我可以强烈建议不要用字符串做所有事情吗?

标签: c# algorithm


【解决方案1】:

试试这个 LINQ“美”。

var idsList = new string[]
{
    "A-28.03.18-B",
    "S-17.05.18-G",
    "L-17.05.18-P",
    "M-28.03.18-T",
    "B-17.05.18-U"
};

var shippingNumbersList = new string[]
{
    "100,200,300",
    "100,900",
    "200,300,100",
    "100,900,300",
    "100,300"
};

var data = idsList
.Zip(shippingNumbersList, (x, y) =>
{
    //parse the entry of the idsList ('x') in a dateTime
    var date = DateTime.Parse(x.Split("-")[1]); //<-- may need to use DateTime.ParseExact(x.Split('-')[1], "dd.MM.yy", CultureInfo.InvariantCulture) - depending on the culture you are using, this will now work on any machine

    //parse the entry of the shippingNumbersList ('y') in a IEnumerable<int>
    var numbers = y.Split(",").Select(int.Parse);

    //make a IEnumerable of the two different data, consisting of (Id, Date, ShippingNumber) <- a single ShippingNumber, thats why we call numbers.Select
    return numbers.Select(number => (Id: x, Date: date, ShippingNumber: number));
}) //<-- use ZIP to combine the two lists together
.SelectMany(x => x) //<-- use SELECTMANY to get a flat list of each "id" with the x number of "shippingNumberList"
.GroupBy(x => (Date: x.Date, ShippingNumber: x.ShippingNumber)) //<-- use GROUPBY for the Date and ShippingNumber
.Where(x => x.Count() > 1) //<-- use WHERE to filter those who only have 1 entry in a group consisting of Date+ShippingNumber
.Select(x => x.Key.ShippingNumber + "-> " + string.Join(",", x.Select(y => y.Id))) //<-- use SELECT to resolve the group to a string, there the Key is the combined Date + ShippingNumber and the Value is the flatList of that group
.ToList(); //<-- use TOLIST to make a List out of the IEnumerable

必须修复一些东西才能在 dotnetfiddle 上运行,但你可以这样: https://dotnetfiddle.net/bKpUDz

【讨论】:

    【解决方案2】:

    这是另一个经过测试的解决方案:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.IO;
    using System.Data;
    using System.Text.RegularExpressions;
    
    namespace ConsoleApplication100
    {
    
        class Program
        {
            static void Main(string[] args)
            {
                List<string> IdsList = new List<string>() {
                                     "A-28.03.18-B",
                                     "S-17.05.18-G", 
                                     "L-17.05.18-P",
                                     "M-28.03.18-T",
                                     "B-17.05.18-U"
                                  };
                List<string> ShippingNumbersList = new List<string>() {
                                                  "100,200,300", 
                                                  "100,900", 
                                                  "200,300,100",
                                                  "100,900,300",
                                                  "100,300"
                                              };
                var results = Shipping.MergeList(IdsList, ShippingNumbersList);
            }
    
        }
        public class Shipping
        {
    
            public static object MergeList(List<string> ids, List<string> numbers)
            {
                string pattern = @"\w-(?'day'[^\.]+)\.(?'month'[^\.]+)\.(?'year'[^-]+)";
    
                List<KeyValuePair<DateTime, string>> idDates = new List<KeyValuePair<DateTime,string>>();
                foreach(string id in ids)
                {
                    Match match = Regex.Match(id,pattern);
                    idDates.Add(new KeyValuePair<DateTime, string>( new DateTime(2000 + int.Parse(match.Groups["year"].Value), int.Parse(match.Groups["month"].Value), int.Parse(match.Groups["day"].Value)), id));
                }
    
                var groups = idDates.SelectMany((x, i) => numbers[i].Split(new char[] {','}).Select(y => new { idDate = x, number = y })).ToList();
    
                var groupDates = groups.GroupBy(x => new { date = x.idDate.Key, number = x.number }).ToList();
    
                var results = groupDates.Select(x => new { number = x.Key.number, ids = x.Select(y => y.idDate.Value).ToList() }).ToList();
    
                return results;
            }
        }
    
    }
    

    【讨论】:

      【解决方案3】:

      数据:

      var IdsList =new string[] {"A-28.03.18-B",
          "S-17.05.18-G",
          "L-17.05.18-P",
          "M-28.03.18-T",
          "B-17.05.18-U" };
      
      var ShippingNumbersList =new string[] {"100,200,300",
                              "100,900",
                              "200,300,100",
                              "100,900,300",
                              "100,300" };
      

      得出结果:

      //normalizing data and make a list of joined columns
      var normalizedlist = IdsList
      .Select((Ids, index) => new { Ids = Ids, ShippingNumbers = ShippingNumbersList[index].Split(',') })
          .ToList();
      //for each distinct ShippingNumber find and write respective Id
      foreach (var ShippingNumber in normalizedlist.SelectMany(x=>x.ShippingNumbers).Distinct())
      {
          //fitering and then grouping by date 
          var filtered = normalizedlist.Where(y => y.ShippingNumbers.Contains(ShippingNumber))
              .GroupBy(y => y.Ids.Split('-')[1])
              .Where(y => y.Count() > 1)
              .Select(y => y.Select(z=>z.Ids));
          foreach (var date in filtered)
          {
          Console.WriteLine($"{ShippingNumber}>>{string.Join(",",date.ToArray())}");
          }
      }
      

      输出:

      100>>A-28.03.18-B,M-28.03.18-T
      100>>S-17.05.18-G,L-17.05.18-P,B-17.05.18-U
      300>>A-28.03.18-B,M-28.03.18-T
      300>>L-17.05.18-P,B-17.05.18-U
      

      【讨论】:

        猜你喜欢
        • 2021-10-05
        • 1970-01-01
        • 1970-01-01
        • 2021-10-24
        • 2018-09-23
        • 1970-01-01
        • 2017-07-11
        • 2021-04-03
        • 2021-11-23
        相关资源
        最近更新 更多