2011-12-28 4 views
16

tôi có một danh sách trong C#:Có một phương pháp AddUnique tương tự như AddRange() cho alist trong C#

 var list = new List<Car>(); 
     list.AddRange(GetGreenCars()); 
     list.AddRange(GetBigCars()); 
     list.AddRange(GetSmallCars()); 

vấn đề là một số trong những chiếc xe tương tự được trả lại trong các chức năng khác nhau và tôi không muốn họ trong danh sách nhiều lần. Mỗi xe có một thuộc tính Tên duy nhất. Có anyway tôi có thể có một cái gì đó như thế này ở trên nhưng sẽ chỉ thêm các mục nếu họ là duy nhất?

Trả lời

13

Một List<T> dường như không có bộ sưu tập thích hợp ở đây. Bạn có thể muốn triển khai ISet<T> chẳng hạn như HashSet<T> (hoặc SortedSet<T> nếu bạn cần đặt hàng).

Để cho phép điều này, bạn sẽ cần phải viết thực hiện IEqualityComparer<T> xác định sự bình đẳng giữa các ô tô theo thuộc tính Name. Nếu đây là định nghĩa về 'bình đẳng' bình đẳng về xe hơi, bạn cũng có thể xem xét trực tiếp việc xây dựng định nghĩa này thành loại Car (object.Equals, object.GetHashCode và cũng lý tưởng triển khai IEquatable<T>).

30

Một lựa chọn là để thêm chúng và loại bỏ những cái lặp đi lặp lại:

var list = new List<Car>(); 
list.AddRange(GetGreenCars()); 
list.AddRange(GetBigCars()); 
list.AddRange(GetSmallCars()); 
list = list.Distinct().ToList(); 
+0

tôi có các đối tượng trùng lặp trong bộ sưu tập của tôi. Đơn giản chỉ cần list = list.Distinct(). ToList(); không hoạt động. – wotney

+2

Riêng biệt sẽ loại bỏ các đối tượng trùng lặp. Nếu các đối tượng của bạn không thực sự giống nhau, bạn phải làm cho các đối tượng của bạn thực hiện Equals() và GetHashCode() – ivowiblo

19

Một lựa chọn khác là để làm một cái gì đó như:

public static void AddUnique<T>(this IList<T> self, IEnumerable<T> items) 
{ 
    foreach(var item in items) 
     if(!self.Contains(item)) 
      self.Add(item) 
} 


var list = new List<Car>(); 
list.AddUnique(GetGreenCars()); 
list.AddUnique(GetBigCars()); 
list.AddUnique(GetSmallCars()); 
+0

Đẹp và đơn giản. – CmdrTallen

3

Tuy nhiên, một tùy chọn sử dụng LINQ:

public static void AddUnique<T>(this IList<T> self, IEnumerable<T> items) 
{ 
    self.AddRange(
    items.Where(x => self.FirstOrDefault(y => y.Name == x.Name) == 
    null).ToList()); 
} 

var list = new List<Car>(); 
list.AddUnique(GetGreenCars()); 
list.AddUnique(GetBigCars()); 
list.AddUnique(GetSmallCars()); 
8

Tôi nghĩ rằng đây là khá giống với Tim Robbins' câu trả lời.

var list = new List<Car>(); 
list.AddRange(GetGreenCars().Where(car => !list.Contains(car))); 
list.AddRange(GetBigCars().Where(car => !list.Contains(car))); 
list.AddRange(GetSmallCars().Where(car => !list.Contains(car))); 

Nếu bạn muốn gia hạn ILI Tôi không thấy lý do tại sao điều này không hiệu quả với bạn.

+0

Đừng quên ghi đè Equals() và GetHashCode() trên Ô tô hoặc nó sẽ không thực sự khớp với đối tượng trong Chứa(). Nếu không, câu trả lời tốt nhất. –

+0

Bạn cũng có thể làm một cái gì đó như thế này để so sánh một ID cụ thể bên trong đối tượng: vm.SearchResults.AddRange (searchResultsOr.Where (listOr =>! SearchResultsAnd.Select (listAnd => listAnd.PostId) .Contains (listOr.PostId))); – Yovav

1

Tôi đã tạo phương thức tiện ích mở rộng chỉ thêm các giá trị duy nhất cho bất kỳ điều gì triển khai ICollection<T> (bao gồm List<T>) từ một số IEnumerable<T>. Không giống như các triển khai sử dụng List<T>.Contains(), phương pháp này cho phép bạn chỉ định biểu thức lambda xác định hai mục có giống nhau hay không.

/// <summary> 
/// Adds only items that do not exist in source. May be very slow for large collections and some types of source. 
/// </summary> 
/// <typeparam name="T">Type in the collection.</typeparam> 
/// <param name="source">Source collection</param> 
/// <param name="predicate">Predicate to determine whether a new item is already in source.</param> 
/// <param name="items">New items.</param> 
public static void AddUniqueBy<T>(this ICollection<T> source, Func<T, T, bool> predicate, IEnumerable<T> items) 
{ 
    foreach (T item in items) 
    { 
     bool existsInSource = source.Where(s => predicate(s, item)).Any(); 
     if (!existsInSource) source.Add(item); 
    } 
} 

Cách sử dụng:

source.AddUniqueBy<Foo>((s, i) => s.Id == i.Id, items); 
0

và nếu bạn muốn so sánh một tài sản (id trong trường hợp này), điều này sẽ làm việc

var list = new List<string>(); 
list.AddRange(GetGreenCars().Where(greencar => !list.Contains(greencar, car => car.id == greencar.id))); 
list.AddRange(GetBigCars().Where(bigcar => !list.Contains(bigcar, car => car.id == bigcar.id))); 
list.AddRange(GetSmallCars().Where(smallcar => !list.Contains(smallcar, car => car.id == smallcar.id)));