9

特定の値の 5 つのファイルをスクラブしています。私は異なる値を予想していませんが、これは私自身の教育目的であるため、アプリケーションで最も人気のある値をカウント、比較、および出力したいと考えています。

例えば:

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

私が望んでいる結果はTOMになることですが、初心者であるため、先に進む方法が本当にわかりません.

考え、提案、または例は大歓迎です。ありがとうございました。

4

6 に答える 6

4

LINQ を使用できる場合は、次のようなクエリを使用して、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"JOHN と 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;
    }
于 2010-01-24T06:35:59.887 に答える
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

これにより、各グループがカウントされ、最も頻度の高いものが最初になるように並べ替えられます。カウントが同じグループが 2 つある場合は、小さい方の値が選択されます。(各グループにはすべて同じ値が含まれているため、キーはカウントされたアイテムです。)

select itemGroup.Key

これは、各グループについて、カウントされたアイテムだけが必要であることを示しています。

return itemsOrderedByCount.FirstOrDefault();

これにより、順序付けられたリストの最初の項目 (カウントが最も高い項目) が取得されます。元のシーケンスが空の場合、null が返されます。

使用法:

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

Assert.AreEqual("TOM", GetMostFrequent(items));
于 2010-01-24T06:16:23.347 に答える
2

使用している .Net / 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);
于 2010-01-24T06:00:00.403 に答える
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);
    }
于 2010-01-24T05:55:02.023 に答える
1

Dictionary (.NET 2.0+) を使用して、各値の繰り返し回数を保持できます。

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

C# 3.0 (.NET 3.5 +) を使用している場合は、次を使用します。

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");
于 2010-01-24T06:00:16.227 に答える
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);
    }
}
于 2010-01-24T05:47:50.870 に答える