Điều đầu tiên cần lưu ý là bạn không thực sự quan tâm đến các phím của từ điển. Bước một do đó là bỏ qua chúng như là không liên quan đến nhiệm vụ trong tay. Chúng tôi sẽ làm việc với thuộc tính Values
của từ điển và tác phẩm giống với bất kỳ tập hợp số nguyên nào khác (hoặc thực sự là bất kỳ loại số nào khác mà chúng tôi có thể so sánh cho bình đẳng).
Có hai cách tiếp cận phổ biến cho vấn đề này, cả hai đều đáng được biết đến.
Đầu tiên sử dụng từ điển khác để giữ số lượng các giá trị:
//Start with setting up the dictionary you described.
Dictionary<string, int> dict = new Dictionary<string, int>{
{"key1", 2},
{"key2", 2},
{"key3", 3},
{"key4", 2},
{"key5", 5},
{"key6", 5}
};
//Create a different dictionary to store the counts.
Dictionary<int, int> valCount = new Dictionary<int, int>();
//Iterate through the values, setting count to 1 or incrementing current count.
foreach(int i in dict.Values)
if(valCount.ContainsKey(i))
valCount[i]++;
else
valCount[i] = 1;
//Finally some code to output this and prove it worked:
foreach(KeyValuePair<int, int> kvp in valCount)//note - not sorted, that must be added if needed
Console.WriteLine("{0} - {1}", kvp.Key, kvp.Value);
Hy vọng rằng điều này là khá đơn giản. Một cách khác là phức tạp hơn nhưng có một số ưu điểm:
//Start with setting up the dictionary you described.
Dictionary<string, int> dict = new Dictionary<string, int>{
{"key1", 2},
{"key2", 2},
{"key3", 3},
{"key4", 2},
{"key5", 5},
{"key6", 5}
};
IEnumerable<IGrouping<int, int>> grp = dict.Values.GroupBy(x => x);
//Two options now. One is to use the results directly such as with the
//equivalent code to output this and prove it worked:
foreach(IGrouping<int, int> item in grp)//note - not sorted, that must be added if needed
Console.WriteLine("{0} - {1}", item.Key, item.Count());
//Alternatively, we can put these results into another collection for later use:
Dictionary<int, int> valCount = grp.ToDictionary(g => g.Key, g => g.Count());
//Finally some code to output this and prove it worked:
foreach(KeyValuePair<int, int> kvp in valCount)//note - not sorted, that must be added if needed
Console.WriteLine("{0} - {1}", kvp.Key, kvp.Value);
(Có lẽ chúng ta muốn sử dụng var
chứ không phải là tiết IEnumerable<IGrouping<int, int>>
, nhưng nó có giá trị là chính xác khi giải thích code).
So sánh trực tiếp, phiên bản này kém hơn - cả phức tạp hơn để hiểu và kém hiệu quả hơn. Tuy nhiên, việc học cách tiếp cận này cho phép một số biến thể ngắn gọn và hiệu quả của cùng một kỹ thuật, vì vậy nó đáng xem xét.
GroupBy()
có một điều tra và tạo một liệt kê khác chứa cặp khóa-giá trị trong đó giá trị là một liệt kê quá. Các lambda x => x
có nghĩa là những gì nó được nhóm lại là chính nó, nhưng chúng tôi đã flexibilty cho các quy tắc nhóm khác nhau hơn thế. Nội dung của grp
trông hơi giống:
{
{Key=2, {2, 2, 2}}
{Key=3, {3}}
{Key=5, {5, 5}}
}
Vì vậy, nếu chúng ta lặp qua một này đối với từng nhóm chúng tôi kéo ra Key
và gọi Count()
vào nhóm, chúng tôi nhận được kết quả chúng ta muốn.
Bây giờ, trong trường hợp đầu tiên chúng tôi tích lũy số của chúng tôi trong một lần truyền O (n) duy nhất, trong khi ở đây chúng ta xây dựng nhóm trong thẻ O (n), và sau đó lấy số đếm trong một O thứ hai (n) vượt qua, làm cho nó kém hiệu quả hơn nhiều. Nó cũng khó hiểu hơn một chút, vậy tại sao phải nhắc đến nó?
Vâng, đầu tiên là một khi chúng ta làm hiểu nó, chúng ta có thể biến dòng:
IEnumerable<IGrouping<int, int>> grp = dict.Values.GroupBy(x => x);
foreach(IGrouping<int, int> item in grp)
Console.WriteLine("{0} - {1}", item.Key, item.Count());
Into:
foreach(var item in dict.Values.GroupBy(x => x))
Console.WriteLine("{0} - {1}", item.Key, item.Count());
Đó là khá súc tích, và trở thành thành ngữ.Nó đặc biệt tốt đẹp nếu chúng ta muốn tiếp tục và làm một cái gì đó phức tạp hơn với các cặp giá trị-đếm khi chúng ta có thể chuỗi này vào một hoạt động khác.
Phiên bản mà đặt kết quả vào một cuốn từ điển có thể còn ngắn gọn hơn vẫn:
var valCount = dict.Values.GroupBy(x => x).ToDictionary(g => g.Key, g => g.Count());
Ở đó, toàn bộ câu hỏi của bạn đã trả lời trong một dòng ngắn, chứ không phải là 6 (cắt ra bình luận) cho người đầu tiên phiên bản.
(Một số có thể thích thay thế dict.Values.GroupBy(x => x)
bằng dict.GroupBy(x => x.Value)
sẽ có cùng kết quả chính xác khi chúng tôi chạy Count()
trên đó. Nếu bạn không chắc chắn lý do tại sao, hãy thử giải quyết).
Ưu điểm khác, là chúng tôi linh hoạt hơn với GroupBy
trong các trường hợp khác. Vì những lý do này, những người đã quen sử dụng GroupBy
có khả năng bắt đầu bằng vạch một dòng dict.Values.GroupBy(x => x).ToDictinary(g => g.Key, g => g.Count());
và sau đó thay đổi thành dạng dài hơn nhưng hiệu quả hơn của phiên bản đầu tiên (nơi chúng tôi tăng tổng số chạy trong từ điển mới) nếu nó đã chứng tỏ điểm phát sóng hiệu suất.
Một chút biết thêm: Bạn có yêu cầu đếm các giá trị không lặp lại? Bạn có thể cho chúng tôi một ví dụ về dữ liệu và đầu ra mong muốn của bạn không? – Alan
Thử nghiệm tăng gấp đôi cho bình đẳng là một thực tế rất có vấn đề. Bạn có thể muốn tránh đề cập đến nó nếu bạn muốn có câu trả lời. Việc sử dụng tính năng khác biệt của Linq(). Count() trên thuộc tính Giá trị là một cách tiếp cận phù hợp với thẻ của bạn. –
Và làm thế nào để bạn muốn kiểm tra sự bình đẳng của đôi ở đây? –