我有一个表,用于记录项目的入库和出库。
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
但是我的lambda表达式可以过滤状态为1的项目
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
答案 0 :(得分:0)
我想不出任何符合您要求的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 == "");
答案 1 :(得分:0)
尝试一下:
// 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)
我不确定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();
我认为也可以在SQL中执行-用ROW_NUMBER
处理具有相同名称和状态的项目,然后排除具有相同ROW_NUMBER
但状态= 0的对应项目的项目
答案 3 :(得分:0)
使用LINQ,您可以按Name
分组,然后计算Status
0
的数量,然后返回所有Status
1
个跳过的{ Status
排序的{1}} 0
个对象。如果Created
多于0
,则不会为该1
返回任何值。
Name
答案 4 :(得分:-1)
假设您只想删除名称出现为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);