按C#中元素的频率对数组进行排序
Sorting array by frequency of elements in C#
这是我目前的情况
int[] numbers = { 3,5,4,3,8,8,5,3,2,1,9,5 };
int[] n = new int[12];
int[] k;
foreach (int number in numbers)
{
n[number]++;
}
Array.Sort(n);
Array.Reverse(n);
foreach (int value in n)
{
Console.WriteLine(value);
}
我知道我遗漏了计算元素频率后对其进行排序的部分,我只是无法理解它。非常感谢您的帮助,谢谢!
What's the problem with your solution ?
尽管您在代码中正确地保留了 table 中称为 n
的数字的频率,因此我将其称为 frequencies
,那么您 Sort
这个数组。此操作会破坏您的解决方案,因为每个频率都与其在数组中位置的相应索引相关联。
例如如果这个数组的一个实例是这个[8,2,1,7,6]。当您对该数组调用 Sort
方法时,结果数组将被排序,数组元素的顺序将是 [1,2,7,6,8]。在调用sort之前,数组的第一个元素表示数字0(第一个元素的索引为0)在我们的numbers
中被找到了8次。排序后,第一个元素是1,也就是说现在0号出现的频率是1,显然是错误的。
如果你想保持你的方式,那么你可以尝试这样的事情:
int[] numbers = { 1,2,2,9,1,2,5,5,5,5,2 };
int[] frequencies = new int[12];
int k = 3;
foreach (int number in numbers)
{
frequencies[number]++;
}
var mostFrequentNumbers = frequencies.Select((frequency, index) => new
{
Number = index,
Frequency = frequency
})
.OrderByDescending(item => item.Frequency)
.Select(item => item.Number)
.Take(k);
foreach (int mostFrequentNumber in mostFrequentNumbers)
{
Console.WriteLine(mostFrequentNumber);
}
Are there any other approaches ?
一个简单的方法是使用像字典这样的数据结构,在其中您可以将数字作为键,将相应的频率作为相应的值。
然后你可以按降序对上述数据结构进行排序,并保留 k 个最频繁出现的数字。
int[] numbers = { 1,2,2,9,1,2,5,5,5,5,2 };
int k = 3;
Dictionary<int, int> numberFrequencies = new Dictionary<int, int>();
foreach (int number in numbers)
{
if(numberFrequencies.ContainsKey(number))
{
numberFrequencies[number] += 1;
}
else
{
numberFrequencies.Add(number, 1);
}
}
var mostFrequentNumbers = numberFrequencies.OrderByDescending(numberFrequency => numberFrequency.Value)
.Take(k)
.Select(numberFrequency => numberFrequency.Key);
foreach (int mostFrequentNumber in mostFrequentNumbers)
{
Console.WriteLine(mostFrequentNumber);
}
您也可以仅使用 LINQ 实现相同的目的:
int[] numbers = { 1,2,2,9,1,2,5,5,5,5,2 };
int k = 3;
var mostFrequentNumbers = numbers.GroupBy(number => number)
.ToDictionary(gr => gr.Key, gr => gr.Count())
.OrderByDescending(keyValue => keyValue.Value)
.Take(k)
.Select(numberFrequency => numberFrequency.Key);
foreach (int mostFrequentNumber in mostFrequentNumbers)
{
Console.WriteLine(mostFrequentNumber);
}
您可以只使用 Linq 扩展:
using System.Linq;
using System.Collections.Generic;
...
private static IEnumerable<int> Solve(int[] numbers, int k) {
return numbers
.GroupBy(x => x)
.OrderByDescending(g => g.Count())
.Select(g => g.Key)
.Take(k);
}
那么您可以拨打:
var numbers = new []{1,2,2,9,1,2,5,5,5,5,2};
var k = 3;
var result = Solve(numbers, k);
foreach (int n in result)
Console.WriteLine(n);
非常简洁:
var frequents = numbers.GroupBy(t => t)
.Where(grp => grp.Count() > 1)
.Select(t => t.Key)
.OrderByDescending(t => t)
.Take(k)
.ToList();
这是我目前的情况
int[] numbers = { 3,5,4,3,8,8,5,3,2,1,9,5 };
int[] n = new int[12];
int[] k;
foreach (int number in numbers)
{
n[number]++;
}
Array.Sort(n);
Array.Reverse(n);
foreach (int value in n)
{
Console.WriteLine(value);
}
我知道我遗漏了计算元素频率后对其进行排序的部分,我只是无法理解它。非常感谢您的帮助,谢谢!
What's the problem with your solution ?
尽管您在代码中正确地保留了 table 中称为 n
的数字的频率,因此我将其称为 frequencies
,那么您 Sort
这个数组。此操作会破坏您的解决方案,因为每个频率都与其在数组中位置的相应索引相关联。
例如如果这个数组的一个实例是这个[8,2,1,7,6]。当您对该数组调用 Sort
方法时,结果数组将被排序,数组元素的顺序将是 [1,2,7,6,8]。在调用sort之前,数组的第一个元素表示数字0(第一个元素的索引为0)在我们的numbers
中被找到了8次。排序后,第一个元素是1,也就是说现在0号出现的频率是1,显然是错误的。
如果你想保持你的方式,那么你可以尝试这样的事情:
int[] numbers = { 1,2,2,9,1,2,5,5,5,5,2 };
int[] frequencies = new int[12];
int k = 3;
foreach (int number in numbers)
{
frequencies[number]++;
}
var mostFrequentNumbers = frequencies.Select((frequency, index) => new
{
Number = index,
Frequency = frequency
})
.OrderByDescending(item => item.Frequency)
.Select(item => item.Number)
.Take(k);
foreach (int mostFrequentNumber in mostFrequentNumbers)
{
Console.WriteLine(mostFrequentNumber);
}
Are there any other approaches ?
一个简单的方法是使用像字典这样的数据结构,在其中您可以将数字作为键,将相应的频率作为相应的值。
然后你可以按降序对上述数据结构进行排序,并保留 k 个最频繁出现的数字。
int[] numbers = { 1,2,2,9,1,2,5,5,5,5,2 };
int k = 3;
Dictionary<int, int> numberFrequencies = new Dictionary<int, int>();
foreach (int number in numbers)
{
if(numberFrequencies.ContainsKey(number))
{
numberFrequencies[number] += 1;
}
else
{
numberFrequencies.Add(number, 1);
}
}
var mostFrequentNumbers = numberFrequencies.OrderByDescending(numberFrequency => numberFrequency.Value)
.Take(k)
.Select(numberFrequency => numberFrequency.Key);
foreach (int mostFrequentNumber in mostFrequentNumbers)
{
Console.WriteLine(mostFrequentNumber);
}
您也可以仅使用 LINQ 实现相同的目的:
int[] numbers = { 1,2,2,9,1,2,5,5,5,5,2 };
int k = 3;
var mostFrequentNumbers = numbers.GroupBy(number => number)
.ToDictionary(gr => gr.Key, gr => gr.Count())
.OrderByDescending(keyValue => keyValue.Value)
.Take(k)
.Select(numberFrequency => numberFrequency.Key);
foreach (int mostFrequentNumber in mostFrequentNumbers)
{
Console.WriteLine(mostFrequentNumber);
}
您可以只使用 Linq 扩展:
using System.Linq;
using System.Collections.Generic;
...
private static IEnumerable<int> Solve(int[] numbers, int k) {
return numbers
.GroupBy(x => x)
.OrderByDescending(g => g.Count())
.Select(g => g.Key)
.Take(k);
}
那么您可以拨打:
var numbers = new []{1,2,2,9,1,2,5,5,5,5,2};
var k = 3;
var result = Solve(numbers, k);
foreach (int n in result)
Console.WriteLine(n);
非常简洁:
var frequents = numbers.GroupBy(t => t)
.Where(grp => grp.Count() > 1)
.Select(t => t.Key)
.OrderByDescending(t => t)
.Take(k)
.ToList();