Danh sách hiệu quả các chuỗi duy nhất C #


86

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 đã nghĩ một từ điển có thể chèn các chuỗi ký tự tốt nhất bằng cách viết dict [str] = false; và liệt kê qua các phím dưới dạng danh sách. Đó có phải là một giải pháp tốt?

Câu trả lời:


111

Nếu bạn đang sử dụng .NET 3.5, HashSet sẽ phù hợp với bạn.

Lớp HashSet <(Of <(T>)>) cung cấp các hoạt động tập hợp hiệu suất cao. Tập hợp là một tập hợp không chứa các phần tử trùng lặp và các phần tử của chúng không theo thứ tự cụ thể.


5
Nhưng a HashSetsẽ mất thứ tự các mục. Một tính năng Listcung cấp.
aggsol

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

Cũng lưu ý rằng HashSet không thể được truy cập thông qua chỉ mục, chỉ thông qua một điều tra viên đối lập với một Danh sách.
Andrew

23

Bạn có thể xem để 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);   

33
Bạn không cần kiểm tra Vùng chứa với HashSet. Bạn chỉ có thể gọi trực tiếp phương thức Add và nó sẽ trả về true hoặc false tùy thuộc vào việc mục đó đã tồn tại hay chưa.
LukeH

1
Câu trả lời nên được chỉnh sửa để loại bỏ lệnh gọi đến Vùng chứa thừa. Đây là tất cả những gì bạn cần để ví dụ trên hoạt động: var collectionWithDup = new [] {"one", "one", "two", "one", "two", "zero"}; var uniqueValues ​​= new HashSet <string> (collectionWithDup);
user3285954

14

Tôi không chắc liệu điều này có được coi là một câu trả lời hay không, nhưng khi đối mặt với nhu cầu về một tập hợp 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 với nhau. Trong trường hợp này, bất cứ khi nào bạn thêm vào tập hợp, hãy làm như sau:

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

Khi xóa các 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ó mục nào khác được thêm vào danh sách, bạn sẽ có một tập hợp duy nhất được sắp xếp theo thứ tự chèn!


10

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

8

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 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ợ 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 yêu cầu .Net 3.5


2

Đây là một giải pháp khác mà không cần 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 - Các giá trị duy nhất trong một mảng

Kiểm tra:

using FluentAssertions;

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

Kiểm tra hiệu suất cho List, HashSetSortedSet. 1 triệu lần lặp:

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

Kiểm tra mã nguồn (ý chính)

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.