我正在为特定值清理5个文件。我不期待任何不同的价值观,但因为这是出于我自己的教育目的,我希望应用程序能够计算,比较和打印最受欢迎的价值。
例如:
ArrayList arrName = new ArrayList();
arrName.Add("BOB")
arrName.Add("JOHN")
arrName.Add("TOM")
arrName.Add("TOM")
arrName.Add("TOM")
我想要的结果是TOM,但作为一个新手,我真的不知道如何前进。
非常感谢任何想法,建议或例子。 谢谢。
答案 0 :(得分: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;
}
答案 1 :(得分: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);
答案 2 :(得分:2)
这是LINQ非常适合的任务。
首先,让我们来定义我们正在做的事情:
此查询实现上述内容:
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));
答案 3 :(得分: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);
}
答案 4 :(得分:1)
您可以使用词典(.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");
答案 5 :(得分: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);
}
}