代码之家  ›  专栏  ›  技术社区  ›  phonemyatt

Lamdba表达式以过滤相同数目的对

  •  0
  • phonemyatt  · 技术社区  · 7 年前

     Id    Name Status Created
     1     A1   1      9/11/2018 14:00:00 <- 1
     2     A1   1      9/11/2018 14:01:00 <- 2
     3     A1   1      9/11/2018 14:02:00 <- 3
     4     A2   1      9/11/2018 14:03:00 <- 4
     5     A3   1      9/11/2018 14:04:00 <- 5
     6     A1   0      9/11/2018 14:05:00 <- consider 1 is taken out.
     7     A1   1      9/11/2018 14:06:00 <- 6
    

    我要过滤这一对;表中的索引1和索引6。给我留下状态为1的项目。正确的表应该如下所示

     Id    Name Status Created
    
     2     A1   1      9/11/2018 14:01:00 <- 2
     3     A1   1      9/11/2018 14:02:00 <- 3
     4     A2   1      9/11/2018 14:03:00 <- 4
     5     A3   1      9/11/2018 14:04:00 <- 5
    
     7     A1   1      9/11/2018 14:06:00 <- 6
    

    public class Item {
       public int Id;
       public string Name;
       public bool Status;
       public DateTime;
    }
    var Items = new List<Item>();
    // This give me everything
    Items = await db.items.Where(i => i.Status == true).ToListAsync();
    

    我拿到了状态为1的所有物品的清单

     Id    Name Status Created
     1     A1   1      9/11/2018 14:00:00 <- 1
     2     A1   1      9/11/2018 14:01:00 <- 2
     3     A1   1      9/11/2018 14:02:00 <- 3
     4     A2   1      9/11/2018 14:03:00 <- 4
     5     A3   1      9/11/2018 14:04:00 <- 5
    
     7     A1   1      9/11/2018 14:06:00 <- 6
    

    如何应用lambda表达式筛选出要从列表中删除的同名对?我想知道有没有用lambda表达式的快捷方式来过滤这样的列表?

    示例:

     Id  Name Status DateTime             Id Name Status DateTime
      6  A1   0      9/11/2018 14:05:00   1  A1   1      9/11/2018 14:00:00
      // this id 1 and id 6 i want to remove based on name and date time
                                          2  A1   1      9/11/2018 14:01:00
                                          3  A1   1      9/11/2018 14:02:00 
                                          4  A2   1      9/11/2018 14:03:00
                                          5  A3   1      9/11/2018 14:04:00
                                          7  A1   1      9/11/2018 14:06:00
    
    5 回复  |  直到 6 年前
        1
  •  0
  •   Sweeper    7 年前

    试试这个:

    // your original data
    var Items = new List<Item>();
    
    // those items with status 0
    var itemsToBeRemoved = Items.Where(x => !x.Status);
    
    // remove those first
    Items.RemoveAll(itemsToBeRemoved.Contains);
    
    // now find the things with the same name, order by date, get the first one.
    var theOtherItemsToBeRemoved = itemsToBeRemoved.Select(x => 
        Items.Where(y => y.Name == x.Name).OrderBy(y => y.Created).FirstOrDefault()
    ).ToList();
    
    // now remove the items found
    Items.RemoveAll(theOtherItemsToBeRemoved.Contains);
    
        2
  •  0
  •   Michał Turczyn    7 年前

    我想不出任何符合您需求的LINQ扩展方法,但您可以通过嵌套循环轻松实现它,如下所示:

      // Data generation
      var items = new List<Item>();
      for (int i = 0; i < 7; i++)
        items.Add(new Item() { Id = i + 1, Dt = DateTime.Parse("9/11/2018 14:00:00").AddMinutes(i), Name = "A1", Status = true });
      items[3].Name = "A2";
      items[4].Name = "A3";
      items[5].Status = false;
    
      // It's also good to make sure that elements are in correct order
      items = items.OrderBy(i => i.Dt).ToList();
    
      // Procedure, to execute your logic
      for (int i = 0; i < items.Count(); i++)
      {
        // If it has Status = true, then look for "enclosing" element with Status = false
        if(items[i].Status)
          for (int j = i + 1; j < items.Count(); j++)
          {
            if(!items[j].Status && items[j].Name == items[i].Name)
            {
              // Mark items, so we delete them (and recognize those with status 0 as used)
              items[i].Name = "";
              items[j].Name = "";
            }
          }
      }
      // Remove all marked elements
      items.RemoveAll(i => i.Name == "");
    
        3
  •  0
  •   Fabio    7 年前

    我不确定LINQ to Entity表达式,但是在内存中加载项之后,可以删除在数据库中被“标记”为已删除的项。

    var items = await db.items.OrderBy(item => item.Created).ToListAsync();
    
    var stillInItems = items.GroupBy(item => item.Name)
                            .Select(group => group.ToLookup(item => item.Status))
                            .SelectMany(lookup => 
                            {
                                var outItemsCount = lookup[false].Count();
                                return lookup[true].Skip(outItemsCount);
                            })
                            .ToList();
    

    ROW_NUMBER 对于具有相同名称和状态的项,然后排除具有相同名称和状态的对应项的项 行\u编号

        4
  •  0
  •   NetMage    7 年前

    使用LINQ,您可以按 Name Status 0 然后归还所有 状态 1 正在跳过的计数 0 对象排序依据 Created . 如果还有更多 0 1. 姓名

    var filtered = src
                    .GroupBy(s => s.Name)
                    .SelectMany(g => { // for each name group
                        var skipCount = g.Where(r => r.Status == 0).Count(); // count the 0 status
                        return g.Where(r => r.Status == 1).OrderBy(r => r.Created).Skip(skipCount); // return the 1 status without earliest matched to 0 status
                    })
                    .OrderBy(s => s.Id);
    
        5
  •  -1
  •   Anapsidae    7 年前

    假设您只想删除每个名称中状态为true和false的第一个实例,我猜这是可行的:

    // Create lookup
    ILookup<string, Item> lookupItems = Items.OrderBy(ordBy => ordBy.Created)
                                             .ToLookup(l => l.Name);
    
    // Iterate through your collection
    Items.RemoveAll(item => lookupItems[item.Name].Any(lookupItem => !lookupItem.Status)
         ? lookupItems[item.Name].First(lookupItem => !lookupItem.Status).Id == item.Id || 
           lookupItems[item.Name].First(lookupItem => lookupItem.Status).Id == item.Id
         : false);