Xóa mục khỏi danh sách dựa trên tình trạng


78

Tôi có một cấu trúc như thế này:

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

và muốn xóa sản phẩm ở vị trí ID1. Hiện
tôi đang thử:

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

và nó không hoạt động.

CẢM ƠN TẤT CẢ

Câu trả lời:


66

Sử dụng linq:

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

Có thể bạn thậm chí muốn sử dụng SingleOrDefault()và kiểm tra xem phần tử có tồn tại hay không ...

CHỈNH SỬA:
stufflà một cấu trúc, SingleOrDefault()sẽ không trả về null. Nhưng nó sẽ trả về mặc định (thứ) , sẽ có ID bằng 0. Khi bạn không có ID bằng 0 cho đối tượng thứ thông thường của mình , bạn có thể truy vấn ID này:

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

1
Khá chắc chắn Remove (null) ném ra một ngoại lệ sẽ loại bỏ vị trí của SingleOrDefault.
Matt Mitchell vào

2
@Graphain: Tôi thêm một ví dụ cho bạn
tanascius

1
Hoặc có thể dễ đọc hơn if (stuffToRemove != default(stuff)).
Rufus L

209

Nếu loại bộ sưu tập của bạn là a List<stuff>, thì cách tiếp cận tốt nhất có lẽ là như sau:

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

Điều này chỉ thực hiện một lần (lặp) qua danh sách, do đó sẽ hiệu quả hơn các phương thức khác.

Nếu kiểu của bạn chung chung hơn ICollection<T>, có thể hữu ích khi viết một phương thức mở rộng ngắn nếu bạn quan tâm đến hiệu suất. Nếu không, thì bạn có thể sử dụng LINQ (gọi Wherehoặc Single).


5
Không thể chấp nhận câu trả lời này vì IList không có RemoveAll. Người khởi xướng chủ đề không chỉ định những gì anh ta / cô ta có: Danh sách <T> hoặc IList <T>.
Evgeni Nabokov

5
"Không thể"? Haha. Đừng hoang mang. Ngay cả khi tác giả đang làm việc với IList, thì việc thực hiện RemoveAll là khá đơn giản.
Noldorin

5

Nếu bạn có LINQ:

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

Bạn có thể đặt bạn wheretruy vấn như một tham số để First ()
Matt Mitchell

Hoặc bạn chỉ có thể thay thế WherevớiFirst
Rufus L


1

Đây là giải pháp cho những ai muốn xóa nó khỏi cơ sở dữ liệu với Entity Framework :

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

Và chính phương thức mở rộng:

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 Điều này mô phỏng phương thức RemoveAll()không có sẵn cho các bộ DB của khung thực thể.


0

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

bạn không thể sửa đổi bộ sưu tập trong foreach, như Vincent gợi ý


Đơn lẻ sẽ chậm hơn so với lần đầu tiên nhưng nó đảm bảo bạn không có sản phẩm trùng lặp cho cùng một ID, đây có thể là điều bạn muốn kiểm tra.
Matt Mitchell vào

0

Bạn chỉ có thể xóa một cái gì đó mà bạn có tham chiếu đến. Vì vậy, bạn sẽ phải tìm kiếm toàn bộ danh sách:

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

hoặc là

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

sử dụng hàm find hoặc findIndex trên danh sách thay vì lặp qua nó có nhanh hơn không?
Rob

1
Bạn không thể sửa đổi các bộ sưu tập bạn đang lặp lại
Matt Mitchell

@Rob, đối với một Danh sách, tìm kiếm phải giống nhau.
Matt Mitchell vào

@Graphain rất tiếc. @Rob, có một phát hiện có lẽ tốt hơn.
Vincent McNabb,

-2

Bạn có thể sử dụng Linq.

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

Thao tác này sẽ không xóa đối tượng. Nếu bạn chỉ định giống như prods = prods.Where(p != 1).ToList()bạn đang ở gần hơn, nhưng điều đó sẽ không sửa đổi danh sách bạn đã được cung cấp làm tham số.
Matt Mitchell vào
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.