2009-05-28 47 views
75

Cách hiệu quả nhất để lưu trữ danh sách các chuỗi bỏ qua bất kỳ bản sao nào? Tôi đã suy nghĩ một từ điển có thể chèn chuỗi tốt nhất bằng cách viết dict [str] = false; và liệt kê thông qua các phím như một danh sách. Đó có phải là một giải pháp tốt?Danh sách hiệu quả các chuỗi duy nhất C#

Trả lời

97

Nếu bạn đang sử dụng .NET 3.5, HashSet sẽ hoạt động cho bạn.

HashSet < (Trong số < (T>)>) lớp cung cấp hoạt động thiết lập hiệu suất cao. Tập hợp là bộ sưu tập không chứa các phần tử trùng lặp và có các thành phần không theo thứ tự cụ thể.

+3

Nhưng một 'HashSet' sẽ mất trật tự của các mặt hàng. Một tính năng mà một 'List' cung cấp. – aggsol

+4

Bổ sung: Ngoài ra còn có SortedSet là một HashSet được sắp xếp thuận tiện. – WhoIsRich

+0

Cũng lưu ý rằng HashSet không thể được truy cập thông qua indice, chỉ thông qua một điều tra viên như trái ngược với một danh sách. – andrew

2

Đây không phải là một phần của không gian tên hệ thống nhưng đã sử dụng Iesi.Collections từ http://www.codeproject.com/KB/recipes/sets.aspx với NHibernate. Nó có hỗ trợ cho bộ băm cùng với bộ được sắp xếp, bộ từ điển, v.v. Kể từ khi nó đã được sử dụng với NHibernate nó đã được sử dụng rộng rãi và rất ổn định. Điều này cũng không đòi hỏi Net 3.5

17

Bạn có thể xem xét để làm một cái gì đó như thế này

var hash = new HashSet<string>(); 
var collectionWithDup = new []{"one","one","two","one","two","zero"}; 

// No need to check for duplicates as the Add method 
// will only add it if it doesn't exist already 
foreach (var str in collectionWithDup) 
    hash.Add(str); 
+32

Bạn không cần kiểm tra Chứa bằng một HashSet.Bạn chỉ có thể gọi phương thức Thêm trực tiếp và nó sẽ trả về true hoặc false tùy thuộc vào mục có tồn tại hay không. – LukeH

+1

Câu trả lời phải được chỉnh sửa để xóa cuộc gọi thành dư thừa Chứa. Điều này tất cả bạn cần cho ví dụ trên để làm việc: var collectionWithDup = new [] {"một", "một", "hai", "một", "hai", "số không"}; var uniqueValues ​​= new HashSet (collectionWithDup); – user3285954

12

Tôi không chắc chắn nếu điều này tính như là một câu trả lời tốt, nhưng khi phải đối mặt với sự cần thiết của một bộ duy nhất duy trì thứ tự chèn, tôi đã thỏa hiệp với một HashSet và một danh sách song song. Trong trường hợp này, bất cứ khi nào bạn thêm vào bộ này, hãy làm như sau:

if(hashSet.Add(item)) 
    orderList.Add(item); 

Khi xóa mục, hãy đảm bảo xóa chúng khỏi cả hai. Vì vậy, miễn là bạn có thể chắc chắn rằng không có gì khác thêm các mục vào danh sách, bạn sẽ có một bộ duy nhất được đặt hàng chèn!

6

Sử dụng HashSet, không cần kiểm tra .Contains(), chỉ cần thêm các mục của bạn vào danh sách và nếu nó trùng lặp, nó sẽ không thêm nó.

HashSet<int> uniqueList = new HashSet<int>(); 
    uniqueList.Add(1); // List has values 1 
    uniqueList.Add(2); // List has values 1,2 
    uniqueList.Add(1); // List has values 1,2 
    Console.WriteLine(uniqueList.Count); // it will return 2 
2

Đây là giải pháp khác mà không sử dụng HashSet.

var items = new List<string>() { "one", "one", "two", "one", "two", "zero" }; 
var uniqueItems = items.Where((item, index) => items.IndexOf(item) == index); 

Nó đã được thông qua từ chủ đề này: javascript - Unique values in an array

Test:

using FluentAssertions; 

uniqueItems.Count().Should().Be(3); 
uniqueItems.Should().BeEquivalentTo("one", "two", "zero"); 

thử nghiệm hiệu suất cho List, HashSetSortedSet. 1 triệu lần lặp:

List: 564 ms 
HashSet: 487 ms 
SortedSet: 1932 ms 

Test source code (gist)

1

Bạn cũng có thể sử dụng LINQ như trong:

using System.Linq; 

var items = new List<string>() { "one", "one", "two", "one", "two", "zero" }; 

List<string> distinctItems = items.Distinct().ToList(); 
Các vấn đề liên quan