简体   繁体   中英

Remove item from list based on condition

I have a struct like this:

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

and want to to remove the product where ID is 1.
I'm trying this currently:

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

and it's not working.

THANKS TO ALL

If your collection type is a List<stuff> , then the best approach is probably the following:

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

This only does one pass (iteration) over the list, so should be more efficient than other methods.

If your type is more generically an ICollection<T> , it might help to write a short extension method if you care about performance. If not, then you'd probably get away with using LINQ (calling Where or Single ).

Using linq:

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

Maybe you even want to use SingleOrDefault() and check if the element exists at all ...

EDIT:
Since stuff is a struct, SingleOrDefault() will not return null. But it will return default( stuff ) , which will have an ID of 0. When you don't have an ID of 0 for your normal stuff-objects you can query for this ID:

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

If you have LINQ:

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

Here is a solution for those, who want to remove it from the database with Entity Framework :

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

And the extension method itself:

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);
        }
    }
}

PS This simulates the method RemoveAll() that's not available for DB sets of the entity framework.

You can only remove something you have a reference to. So you will have to search the entire list:

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

or

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

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

正如文森特所建议的,您不能在 foreach 中修改集合

A bit late to the game, however, a simple extension method can implement a RemoveAll on IList<T> . The trick is to loop over the collection in reverse order to avoid the extra logic of deleting the current item and having to try on the current index if removed. Also the reverse order prevents having to copy all the remaining items. Depending on the .NET version, this copy could be expensive.

    public static int RemoveAll<T>(this IList<T> list, Predicate<T> match)
    {
        if (list == null) throw new ArgumentNullException("list");
        if (match == null) throw new ArgumentNullException("match");

        int count = 0;
        for (int i = list.Count - 1; i >= 0; i--)
        {
            if (match(list[i]))
            {
                ++count;
                list.RemoveAt(i);
            }
        }
        return count;
    }

You could use Linq.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM