【问题标题】:Remove item from list based on condition根据条件从列表中删除项目
【发布时间】:2011-03-17 18:54:07
【问题描述】:

我有一个这样的结构:

public struct stuff
{
    public int ID;
    public int quan;
}

并想删除ID 为 1 的产品。
我目前正在尝试这个:

prods.Remove(new stuff{ prodID = 1});

它不工作。

感谢大家

【问题讨论】:

    标签: c# .net entity-framework linq


    【解决方案1】:

    使用 linq:

    prods.Remove( prods.Single( s => s.ID == 1 ) );
    

    也许您甚至想使用SingleOrDefault() 并检查该元素是否存在...

    编辑:
    由于stuff 是一个结构,SingleOrDefault() 不会返回 null。但它会返回 default( stuff ),其 ID 为 0。当您的 normal 东西对象的 ID 没有 0 时,您可以查询对于此 ID:

    var stuffToRemove = prods.SingleOrDefault( s => s.ID == 1 );
    if( stuffToRemove.ID != 0 )
    {
        prods.Remove( stuffToRemove );
    }
    

    【讨论】:

    • 相当肯定 Remove(null) 会抛出一个异常,排除 SingleOrDefault 它所在的位置。
    • @Graphain:我给你加了一个例子
    • 或者可能更具可读性if (stuffToRemove != default(stuff))
    【解决方案2】:

    对于那些想要使用 Entity Framework 将其从 数据库 中删除的人来说,这是一个解决方案:

    prods.RemoveWhere(s => s.ID == 1);

    以及扩展方法本身:

    using System;
    using System.Linq;
    using System.Linq.Expressions;
    using Microsoft.EntityFrameworkCore;
    
    namespace LivaNova.NGPDM.Client.Services.Data.Extensions
    {
        public static class DbSetExtensions
        {
            public static void RemoveWhere<TEntity>(this DbSet<TEntity> entities, Expression<Func<TEntity, bool>> predicate) where TEntity : class
            {
                var records = entities
                    .Where(predicate)
                    .ToList();
                if (records.Count > 0)
                    entities.RemoveRange(records);
            }
        }
    }
    
    

    附:这模拟了实体框架的数据库集不可用的方法RemoveAll()

    【讨论】:

      【解决方案3】:
      prods.Remove(prods.Find(x => x.ID == 1));
      

      【讨论】:

        【解决方案4】:

        如果您的集合类型是List&lt;stuff&gt;,那么最好的方法可能是以下:

        prods.RemoveAll(s => s.ID == 1)
        

        这只对列表进行一次遍历(迭代),因此应该比其他方法更有效。

        如果您的类型更通用的是ICollection&lt;T&gt;,如果您关心性能,那么编写一个简短的扩展方法可能会有所帮助。如果没有,那么您可能会使用 LINQ(调用 WhereSingle)。

        【讨论】:

        • 这个答案不能被接受,因为 IList 没有 RemoveAll。主题发起者未指定他/她拥有什么:List 或 IList.
        • “不能”?哈哈。不要迂腐。即使作者正在使用 IList,RemoveAll 也很容易实现。
        • 如何将类型转换为列表 ((List) prods).RemoveAll(s => s.ID == 1)
        【解决方案5】:

        您只能删除您有参考的内容。所以你必须搜索整个列表:

        stuff r;
        foreach(stuff s in prods) {
          if(s.ID == 1) {
              r = s;
              break;
          }
        }
        prods.Remove(r);
        

        for(int i = 0; i < prods.Length; i++) {
            if(prods[i].ID == 1) {
                prods.RemoveAt(i);
                break;
            }
        }
        

        【讨论】:

        • 在列表中使用 find 或 findIndex 函数不是更快吗?
        • 你不能修改你正在迭代的集合
        • @Rob,对于 List,find 应该是一样的。
        • @Graphain 哎呀。 @Rob,是的,找到可能更好。
        【解决方案6】:

        你可以使用 Linq。

        var prod = from p in prods
                   where p.ID != 1
                   select p;
        

        【讨论】:

        • 这不会删除对象。如果您像 prods = prods.Where(p != 1).ToList() 一样分配,您会更接近,但这不会修改您作为参数提供的列表。
        【解决方案7】:

        prods.Remove(prods.Single(p=&gt;p.ID == 1));

        你不能像文森特建议的那样在 foreach 中修改集合

        【讨论】:

        • Single 会比第一个慢,但它确实保证您没有相同 ID 的重复产品,这可能是您想要检查的东西。
        【解决方案8】:

        如果你有 LINQ:

        var itemtoremove = prods.Where(item => item.ID == 1).First();
        prods.Remove(itemtoremove)
        

        【讨论】:

        • 您可以将where 查询作为参数传递给First()
        • 或者你可以把Where替换成First
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-02-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-31
        相关资源
        最近更新 更多