2010-01-24 46 views
9

我正在爲特定值擦除5個文件。我沒有預料到任何不同的值,但因爲這是爲了我自己的教育目的,我希望應用程序能夠計數,比較和打印最流行的值。System.Collections.ArrayList中的比較/計數值

例如:

ArrayList arrName = new ArrayList(); 
arrName.Add("BOB") 
arrName.Add("JOHN") 
arrName.Add("TOM") 
arrName.Add("TOM") 
arrName.Add("TOM") 

我想結果會是TOM但作爲一個新手,我真的不知道如何前進。

任何想法,建議或例子,非常感謝。 謝謝。

回答

1

可以使用詞典(.NET 2.0+如果您正在使用C#3.0(.NET 3.5 +

Dictionary<string, int> counts = new Dictionary<string, int>(); 
foreach (string name in arrName) { 
    int count; 
    if (counts.TryGetValue(name, out count)) { 
     counts[name] = count + 1; 
    } else { 
     counts.Add(name, 1); 
    } 
} 

// and then look for the most popular value: 

string mostPopular; 
int max = 0; 
foreach (string name in counts.Keys) { 
    int count = counts[name]; 
    if (count > max) { 
     mostPopular = name; 
     max = count; 
    } 
} 

// print it 
Console.Write("Most popular value: {0}", mostPopular); 

),然後使用::)來保存每個值的重複計數

var mostPopular = (from name in arrName.Cast<string>() 
        group name by name into g 
        orderby g.Count() descending 
        select g.Key).FirstOrDefault(); 

Console.Write("Most popular value: {0}", mostPopular ?? "None"); 
0

要通過循環移動,你可以使用一個foreach

foreach (string name in arrName) { 
    Console.WriteLine(i); 
} 

並計算的值,可以使用Hashtable,其鍵映射到值。關鍵字可以是一個名字,值可以是你在列表中看過那個名字的次數。

Hashtable nameHash = new Hashtable(); 
foreach (string name in arrName) { 
    if (!nameHash.ContainsKey(name)) { 
     nameHash.Add(name, 1); 
    } 
    else { 
     int num = nameHash[name]; 
     nameHash.Add(name, num + 1); 
    } 
} 
1
public static string GetMostPopular(ArrayList vals) 
    { 
     IDictionary<string, int> dict = new Dictionary<string, int>(); 
     int mx = 0; 
     string ret = ""; 
     foreach (string x in vals) 
     { 
      if (!dict.ContainsKey(x)) 
      { 
       dict[x] = 1; 
      } 
      else 
      { 
       dict[x]++; 
      } 
      if (dict[x] > mx) 
      { 
       mx = dict[x]; 
       ret = x; 
      } 
     } 
     return ret; 
    } 

    static void Main() 
    { 
     ArrayList arrName = new ArrayList(); 
     arrName.Add("BOB"); 
     arrName.Add("JOHN"); 
     arrName.Add("TOM"); 
     arrName.Add("TOM"); 
     arrName.Add("TOM"); 
     string ans = GetMostPopular(arrName); 
     Console.WriteLine(ans); 
    } 
2

您沒有指定要使用的淨/ C#版本,所以我會好好對待這對於C#的每個版本:V1,V2和V3。

C#V1:

class CountValueComparer : IComparer 
{ 
    public int Compare(object x, object y) 
    { 
     DictionaryEntry left = (DictionaryEntry)x; 
     DictionaryEntry right = (DictionaryEntry)y; 

     return ((int)left.Value).CompareTo((int)right.Value); 
    } 
} 

Hashtable counts = new Hashtable(); 

foreach(String value in arrName) 
{ 
    if (counts.ContainsKey(value)) 
    { 
     int valueCount = (int)counts[value]; 
     ++valueCount; 
     counts[value] = valueCount; 
    } 
    else 
    { 
     counts[value] = 1; 
    } 
} 

DictionaryEntry[] sorted = new DictionaryEntry[counts.Count]; 
counts.CopyTo(sorted, 0); 
Array.Sort(sorted, new CountValueComparer()); 

foreach (DictionaryEntry entry in sorted) 
{ 
    Console.Writeline("Name: {0}; Count: {1}", entry.Key, entry.Value); 
} 

C#V2:

class CountValueComparer : IComparer<KeyValuePair<String, int>> 
{ 
    public int Compare(int x, int y) 
    { 
     return x.Value.CompareTo(y.Value); 
    } 
} 

// if v2, use the List<T> class! 
List<String> arrName = new List<String>(); 

arrName.Add("TOM"); 
// etc... 

Dictionary<String, int> counts = new Dictionary<String, int>(); 

foreach(String value in arrName) 
{ 
    int count; 
    if (counts.TryGetValue(value, out count)) 
    { 
     counts[value] = ++count; 
    } 
    else 
    { 
     counts[value] = 1; 
    } 
} 

KeyValuePair<String, int>[] sorted = new KeyValuePair<String, int>[counts.Count]; 
counts.CopyTo(sorted, 0); 
Array.Sort(sorted, new CountValueComparer()); 

C#V3:

// if v3, use the List<T> class! 
var arrName = new List<String>(); 

arrName.Add("TOM"); 
// etc... 

var counts = (from n in arrName 
       group n by n into g 
       select new { Name = g.Key, Count = g.Count() }) 
       .OrderByDescending(x => x.Count); 
var top = counts.FirstOrDefault(); 
Console.WriteLine("Name: {0}; Count: {1}", top.Name, top.Count); 
2

這是一種任務,對於這LINQ是非常適合。

首先,讓我們來定義我們正在做的事情:

  1. 集團的項目按值
  2. 計算每個組
  3. 返回其組具有最高計數

此項目查詢實現上述:

private string GetMostFrequent(IEnumerable<string> items) 
{ 
    var itemsOrderedByCount = 
     from item in items 
     group item by item into itemGroup 
     orderby itemGroup.Count() descending, itemGroup.Key 
     select itemGroup.Key; 

    return itemsOrderedByCount.FirstOrDefault(); 
} 

該實現非常類似於高級描述,這是聲明性語法的一個很好的副作用。下面是每個部分的快速解釋:

from item in items 

就像循環聲明; item引用循環變量。

group item by item into itemGroup 

這將根據其值將每個item放在一個組中。

orderby itemGroup.Count() descending, itemGroup.Key 

這對每組進行計數並對它們進行排序,使得最頻繁的是第一組。如果有兩組具有相同計數的組,則選擇較小的值。 (由於每個組包含所有相同的價值觀,關鍵是計算的項目。)

select itemGroup.Key 

這就是說每個組,我們只想計項目。

return itemsOrderedByCount.FirstOrDefault(); 

這抓取了有序列表中的第一個項目(計數最高的項目)。如果原始序列爲空,則返回null。

用法:

var items = new[] { "BOB", "JOHN", "TOM", "TOM", "TOM" }; 

Assert.AreEqual("TOM", GetMostFrequent(items)); 
4

您可以輕鬆地與LINQ做,如果你可以使用它,類似於

names.Distinct().OrderByDescending(s => names.Count(u => u == s))).FirstOrDefault(); 

查詢將返回值最高數,或default(Type) 。在等同計數的情況下,它將返回第一個具有最高計數的計數。您可以將此方法放入您的擴展中,並使用泛型進行常規用法。

class Program 
{ 
    static void Main(string[] args) 
    { 

     IEnumerable<String> names = new String[] { "BOB", 
                "JOHN", 
                "TOM", 
                "TOM", 
                "TOM" }; 
     var res = names.Top(); //returns "TOM" 
    } 
} 

public static class Extensions 
{ 

    public static T Top<T>(this IEnumerable<T> values) 
    { 
     return values.Distinct().OrderByDescending(s => values.Count(u => u.Equals(s))).FirstOrDefault(); 
    } 
} 

如果您需要具有最高計數的所有值,比如,如果你的名單是"BOB", "JOHN", "JOHN", "TOM", "TOM"我想你可以使用此版本中,而不是爲了回報這兩個約翰和湯姆:

public static IEnumerable<T> Top<T>(this IEnumerable<T> values) 
    { 
     List<T> ret = new List<T>(); 
     int max = -1; 

     foreach (var val in values.Distinct()) 
     { 
      int count = values.Count(t => t.Equals(val)); 

      if (count >= max) 
      { 
       if (count > max) 
       { 
        ret.Clear(); 
        max = count; 
       } 
       ret.Add(val); //stacks equivalent count, if applicable 
      } 
     } 

     return ret; 
    }