2008-10-24 4 views
6

Tôi có một mảng bản chất của các cặp giá trị tên là một mảng răng cưa - tôi cần phải tạo một tập hợp các giá trị tên duy nhất từ ​​này. mảng răng cưa là khoảng 86.000 x 11 giá trị. Nó không quan trọng với tôi cách mà tôi phải lưu trữ một cặp giá trị tên (một chuỗi duy nhất "name = value" hoặc một lớp chuyên biệt ví dụ KeyValuePair).
Thông tin bổ sung: Có 40 tên riêng biệt và số lượng giá trị khác biệt lớn hơn - có thể trong khu vực 10.000 giá trị.cách nhanh nhất để tạo một tập hợp duy nhất trong .net 2

Tôi đang sử dụng C# và .NET 2.0 (và hiệu năng quá kém tôi nghĩ rằng tốt hơn hết là nên đẩy toàn bộ mảng bị lởm chởm của tôi vào cơ sở dữ liệu sql và chọn riêng biệt ở đó).

Dưới đây là mã hiện Im sử dụng:

List<List<KeyValuePair<string,string>>> vehicleList = retriever.GetVehicles(); 
this.statsLabel.Text = "Unique Vehicles: " + vehicleList.Count; 

Dictionary<KeyValuePair<string, string>, int> uniqueProperties = new Dictionary<KeyValuePair<string, string>, int>(); 
foreach (List<KeyValuePair<string, string>> vehicle in vehicleList) 
{ 
    foreach (KeyValuePair<string, string> property in vehicle) 
    { 
     if (!uniqueProperties.ContainsKey(property)) 
     { 
      uniqueProperties.Add(property, 0); 
     } 
    } 
} 
this.statsLabel.Text += "\rUnique Properties: " + uniqueProperties.Count; 
+0

Bạn có thể đưa ra một số ví dụ về dữ liệu trông như thế nào? Tôi không chắc tôi hiểu những gì bạn đang cố gắng làm ở đây. Bạn có muốn một bộ trên các phím, hoặc các cặp? –

+0

Tôi có thảm - Tôi không hoàn toàn hiểu được vị trí của mảng răng cưa. Một số mã mẫu hiển thị dữ liệu đầu vào sẽ thực sự tiện dụng. –

+0

Trong mảng lởm chởm của bạn, có nhiều mối tương quan giữa tên và giá trị không? Bạn đang cố gắng để có được một mối tương quan một hoặc một hoặc một đến nhiều tương quan như đầu ra (một lần nữa tên cho các giá trị)? Nếu bạn có thể trả lời câu hỏi này, thì tôi có thể cung cấp câu trả lời tốt hơn. –

Trả lời

12

tôi có nó chạy trong 0,34 giây xuống từ 9 + phút

Vấn đề là khi so sánh các cấu trúc KeyValuePair. Tôi đã làm việc xung quanh nó bằng cách viết một đối tượng so sánh và chuyển một thể hiện của nó đến từ điển.

Từ những gì tôi có thể xác định, KeyValuePair.GetHashCode() trả về mã băm của đối tượng Key (trong ví dụ này là đối tượng ít nhất duy nhất).

Khi từ điển thêm (và kiểm tra sự tồn tại của) mỗi mục, nó sử dụng cả hàm bình đẳng và hàm GetHashCode, nhưng phải dựa vào hàm bình đẳng khi hàm băm nhỏ hơn.

Bằng cách cung cấp chức năng GetHashCode độc ​​đáo hơn, nó trích xuất hàm Equals ít thường xuyên hơn. Tôi cũng đã tối ưu hóa hàm Equals để so sánh các giá trị độc đáo hơn trước các phím ít unqiue.

86.000 * 11 mục có 10.000 đặc tính độc đáo chạy trong 0,34 giây bằng cách sử dụng đối tượng Comparer dưới đây (không có đối tượng Comparer phải mất 9 phút 22 giây)

Hope this helps :)

class StringPairComparer 
     : IEqualityComparer<KeyValuePair<string, string>> 
    { 
     public bool Equals(KeyValuePair<string, string> x, KeyValuePair<string, string> y) 
     { 
      return x.Value == y.Value && x.Key == y.Key; 
     } 
     public int GetHashCode(KeyValuePair<string, string> obj) 
     { 
      return (obj.Key + obj.Value).GetHashCode(); 
     } 
    } 

EDIT: Nếu nó chỉ là một chuỗi (thay vì một KeyValuePair, trong đó string = Tên + Giá trị) nó sẽ là khoảng hai lần nhanh. Đó là một vấn đề tốt đẹp intresting, và tôi đã dành faaaaaar quá nhiều thời gian vào nó (Tôi đã học được một chút yên tĩnh)

0

nếu bạn không cần bất kỳ sự tương quan cụ thể giữa mỗi cặp khóa/giá trị và các giá trị độc đáo mà bạn đang tạo ra, bạn chỉ có thể sử dụng một GUID? Tôi giả định vấn đề là 'Key' hiện tại của bạn không phải là duy nhất trong mảng răng cưa này.

Dictionary<System.Guid, KeyValuePair<string, string>> myDict 
    = new Dictionary<Guid, KeyValuePair<string, string>>(); 


foreach of your key values in their current format 
    myDict.Add(System.Guid.NewGuid(), new KeyValuePair<string, string>(yourKey, yourvalue)) 

Âm thanh như nó sẽ lưu trữ những gì bạn cần nhưng tôi không biết làm thế nào bạn sẽ lấy dữ liệu trở lại từ này như sẽ không có mối quan hệ ngữ nghĩa giữa tạo Guid & những gì bạn ban đầu có ...

Bạn có thể cung cấp thêm bất kỳ thông tin nào trong câu hỏi của mình không?

0

Sử dụng KeyValuePair làm lớp trình bao bọc và sau đó tạo từ điển để tạo tập hợp có lẽ? Hoặc thực hiện trình bao bọc của riêng bạn ghi đè bằng Equals và GetHashCode.

Dictionary<KeyValuePair, bool> mySet; 

for(int i = 0; i < keys.length; ++i) 
{ 
    KeyValuePair kvp = new KeyValuePair(keys[i], values[i]); 
    mySet[kvp] = true; 
} 
0

Làm thế nào về:

Dictionary<NameValuePair,int> hs = new Dictionary<NameValuePair,int>(); 
foreach (i in jaggedArray) 
{ 
    foreach (j in i) 
    { 
     if (!hs.ContainsKey(j)) 
     { 
      hs.Add(j, 0); 
     } 
    } 
} 
IEnumerable<NameValuePair> unique = hs.Keys; 

tất nhiên, nếu bạn đang sử dụng C# 3.0, .NET 3.5:

var hs = new HashSet<NameValuePair>(); 
hs.UnionWith(jaggedArray.SelectMany(item => item)); 

sẽ làm các trick.

+0

đây gần như chính xác mã mà tôi hiện đang sử dụng - không may sau khoảng 20 phút tôi bị thiếu kiên nhẫn và giết ứng dụng. – dice

+0

Trong C# 3, bạn cũng có thể sử dụng '.Distinct()'. –

+0

@ Konrad Rudolph: Có, và nó sẽ chỉ là chậm. –

0

Bạn đã lược tả mã của mình chưa? Bạn chắc chắn rằng các vòng lặp foreach là nút cổ chai, và không phải là retriever.GetVehicles()?

Tôi đã tạo một dự án thử nghiệm nhỏ nơi tôi giả mạo trình thu thập và để cho nó trả lại giá trị 86.000 X 11. Nỗ lực đầu tiên của tôi chạy lúc 5 giây, tạo dữ liệu đi kèm.

Tôi đã sử dụng cùng một giá trị cho cả khóa và giá trị trong đó khóa đầu tiên là "0 # 0" và "85999 # 10" cuối cùng.

Sau đó, tôi chuyển sang guids. Cùng một kết quả.

Sau đó, tôi làm còn chìa khóa, như thế này:

 var s = Guid.NewGuid().ToString(); 
     return s + s + s + s + s + s + s+ s + s + s; 

Bây giờ nó mất gần 10 giây.

Sau đó, tôi đã thực hiện các khóa một cách điên rồ và có một ngoại lệ bộ nhớ. Tôi không có tệp hoán đổi trên máy tính của mình, vì vậy tôi đã nhận được ngoại lệ này ngay lập tức.

Phím của bạn dài bao lâu? Bộ nhớ ảo của bạn có tiêu thụ lý do cho hiệu suất kém của bạn không?

+0

GetVehicles() khá nhanh trong trường hợp của tôi - sự khác biệt mà tôi đoán là dữ liệu - dữ liệu của bạn sẽ chứa tất cả các giá trị duy nhất trong khi tôi không - nó vẫn đáng ngạc nhiên khi nó chạy nhanh như thế nào. Nó phải là 86.000 trong vòng ngoài và 11 ở bên trong. – dice