2008-12-10 23 views
19

Có cách nào nhanh chóng và đẹp mắt bằng LINQ không?Tìm số xuất hiện nhiều nhất trong Danh sách <int>

+0

@AakashM, Gần như chắc chắn rằng bằng biểu thức lambda OP có nghĩa là LINQ, chứ không phải một số cách tiếp cận đại biểu/biểu thức. Không biết tại sao bản chỉnh sửa được hoàn nguyên. – nawfal

+0

@nawfal 1) không có cách nào để nghi ngờ người dùng chưa đăng ký này có nghĩa là 4 năm trước, thậm chí ít hơn là 'gần như chắc chắn'.2) [tag: find-occurrences] là thẻ nghèo và trong mọi trường hợp thẻ không phù hợp. 3) Từ "linq" không phải là mã và do đó không được định dạng thành mã. Ba phần quan trọng nhất để chỉnh sửa cho tâm trí của tôi tạo ra cơ sở hoàn toàn tốt cho việc đảo ngược, nhưng hãy thoải mái đưa nó vào meta nếu bạn không đồng ý. – AakashM

+0

@AakashM Tôi đồng ý với 3. Tuy nhiên, ý chính của bản chỉnh sửa của tôi là một câu hỏi hợp lý hơn. Bạn có thể đã xóa thẻ không phù hợp (?) Và cũng là định dạng mã nếu đó là điều quan trọng bằng cách chỉnh sửa thay vì hoàn nguyên. Vì vậy, bây giờ, * trong mọi trường hợp thẻ không phù hợp *, do đó, đối với loại câu hỏi nào thì nó phù hợp hơn ?. 2) những gì bạn nghĩ rằng OP phải có nghĩa là bởi * biểu thức lambda *? Điểm của tôi là có ** là một cách để nghi ngờ ** đã ở trong vòng tròn C# một thời gian, và một nghi ngờ mạnh mẽ của nó cho câu trả lời OP đã chọn. – nawfal

Trả lời

60

Làm thế nào về:

var most = list.GroupBy(i=>i).OrderByDescending(grp=>grp.Count()) 
     .Select(grp=>grp.Key).First(); 

hoặc trong cú pháp truy vấn:

var most = (from i in list 
      group i by i into grp 
      orderby grp.Count() descending 
      select grp.Key).First(); 

Tất nhiên, nếu bạn sẽ sử dụng nhiều lần, bạn có thể thêm một phương pháp khuyến nông:

public static T MostCommon<T>(this IEnumerable<T> list) 
{ 
    return ... // previous code 
} 

Sau đó, bạn có thể sử dụng:

var most = list.MostCommon(); 
+0

Đó là những gì tôi đã cố gắng để đạt được, nhưng bộ não của tôi chỉ không hoạt động vào lúc này. –

+5

Điều gì xảy ra nếu nhiều hơn một phần tử là câu trả lời? –

+1

@Varun - câu hỏi hay; nhưng không khó để thích ứng với phù hợp với –

4

Không chắc về các biểu thức lambda, nhưng tôi sẽ

  1. Sắp xếp danh sách [O (n log n)]

  2. Quét danh sách [O (n)] tìm thời gian dài nhất -chiều dài.

  3. Quét lại lần nữa [O (n)] báo cáo mỗi số có độ dài chạy đó.

Điều này là do có thể có nhiều hơn một số xuất hiện nhiều nhất.

0

Ai đó đã yêu cầu giải pháp có quan hệ. Dưới đây là một đâm vào rằng:

int indicator = 0 

var result = 
    list.GroupBy(i => i) 
    .Select(g => new {i = g.Key, count = g.Count()} 
    .OrderByDescending(x => x.count) 
    .TakeWhile(x => 
    { 
     if (x.count == indicator || indicator == 0) 
     { 
     indicator = x.count; 
     return true; 
     } 
     return false; 
    }) 
    .Select(x => x.i); 
2

Taken từ câu trả lời của tôi here:

public static IEnumerable<T> Mode<T>(this IEnumerable<T> input) 
{    
    var dict = input.ToLookup(x => x); 
    if (dict.Count == 0) 
     return Enumerable.Empty<T>(); 
    var maxCount = dict.Max(x => x.Count()); 
    return dict.Where(x => x.Count() == maxCount).Select(x => x.Key); 
} 

var modes = { }.Mode().ToArray(); //returns { } 
var modes = { 1, 2, 3 }.Mode().ToArray(); //returns { 1, 2, 3 } 
var modes = { 1, 1, 2, 3 }.Mode().ToArray(); //returns { 1 } 
var modes = { 1, 2, 3, 1, 2 }.Mode().ToArray(); //returns { 1, 2 } 

tôi đã đi cho một thử nghiệm hiệu suất giữa các cách tiếp cận trên và David B'sTakeWhile.

source = {}, iterations = 1000000
tôi - 300 ms, David - 930 ms

source = {1}, iterations = 1000000
tôi - 1070 ms, David - 1560 ms

source = 100 ints với 2 bản sao, iterations = 10000
tôi - 300 ms, David - 500 ms

source = 10000 ints ngẫu nhiên với khoảng 100 d uplicates, lặp đi lặp lại = 1.000
tôi - 1280 ms, David - 1400 ms

1

Dưới đây là một câu trả lời, mà dường như được nhanh chóng. Tôi nghĩ rằng Nawfal's answer nói chung là nhanh hơn nhưng điều này có thể làm bóng nó trên chuỗi dài.

public static IEnumerable<T> Mode<T>(
    this IEnumerable<T> source, 
    IEqualityComparer<T> comparer = null) 
{ 
    var counts = source.GroupBy(t => t, comparer) 
     .Select(g => new { g.Key, Count = g.Count() }) 
     .ToList(); 

    if (counts.Count == 0) 
    { 
     return Enumerable.Empty<T>(); 
    } 

    var maxes = new List<int>(5); 
    int maxCount = 1; 

    for (var i = 0; i < counts.Count; i++) 
    { 
     if (counts[i].Count < maxCount) 
     { 
      continue; 
     } 

     if (counts[i].Count > maxCount) 
     { 
      maxes.Clear(); 
      maxCount = counts[i].Count; 
     } 

     maxes.Add(i); 
    } 

    return maxes.Select(i => counts[i].Key); 
} 
+0

Điều này xứng đáng được cập nhật :) – nawfal

+0

@nawfal thực sự, đã đồng ý và thực hiện. – Jodrell

Các vấn đề liên quan