104

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

Just Shadow
  • 10,860
  • 6
  • 57
  • 75

9 Answers9

264

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).

Noldorin
  • 144,213
  • 56
  • 264
  • 302
82

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 );
}
Aristos
  • 66,005
  • 16
  • 114
  • 150
tanascius
  • 53,078
  • 22
  • 114
  • 136
9

If you have LINQ:

var itemtoremove = prods.Where(item => item.ID == 1).First();
prods.Remove(itemtoremove)
Nathan W
  • 54,475
  • 27
  • 99
  • 146
3
prods.Remove(prods.Find(x => x.ID == 1));
Alex
  • 576
  • 3
  • 8
2

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

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

Just Shadow
  • 10,860
  • 6
  • 57
  • 75
0

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;
    }
}
Vincent McNabb
  • 33,327
  • 7
  • 31
  • 53
0

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

you can't modify collection in foreach, as Vincent suggests

Kikaimaru
  • 1,841
  • 1
  • 16
  • 28
  • Single would be slower than first but it does guarantee you don't have duplicate products for the same ID which may be something you want to check for. – Matt Mitchell Jul 19 '10 at 07:37
0

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;
    }
Phil Bolduc
  • 1,586
  • 1
  • 11
  • 19
-2

You could use Linq.

var prod = from p in prods
           where p.ID != 1
           select p;
Chris
  • 1,197
  • 4
  • 13
  • 25
  • This won't remove the object. If you assign like `prods = prods.Where(p != 1).ToList()` you're closer, but that won't modify a list you've been given as a parameter. – Matt Mitchell Jul 19 '10 at 07:38