How to get the most common value in an Int array? (C#) - c#

How to get the most common value in an Int array using C#
eg: Array has the following values: 1, 1, 1, 2
Ans should be 1

var query = (from item in array
group item by item into g
orderby g.Count() descending
select new { Item = g.Key, Count = g.Count() }).First();
For just the value and not the count, you can do
var query = (from item in array
group item by item into g
orderby g.Count() descending
select g.Key).First();
Lambda version on the second:
var query = array.GroupBy(item => item).OrderByDescending(g => g.Count()).Select(g => g.Key).First();

Some old fashioned efficient looping:
var cnt = new Dictionary<int, int>();
foreach (int value in theArray) {
if (cnt.ContainsKey(value)) {
cnt[value]++;
} else {
cnt.Add(value, 1);
}
}
int mostCommonValue = 0;
int highestCount = 0;
foreach (KeyValuePair<int, int> pair in cnt) {
if (pair.Value > highestCount) {
mostCommonValue = pair.Key;
highestCount = pair.Value;
}
}
Now mostCommonValue contains the most common value, and highestCount contains how many times it occured.

I know this post is old, but someone asked me the inverse of this question today.
LINQ Grouping
sourceArray.GroupBy(value => value).OrderByDescending(group => group.Count()).First().First();
Temp Collection, similar to Guffa's:
var counts = new Dictionary<int, int>();
foreach (var i in sourceArray)
{
if (!counts.ContainsKey(i)) { counts.Add(i, 0); }
counts[i]++;
}
return counts.OrderByDescending(kv => kv.Value).First().Key;

public static int get_occure(int[] a)
{
int[] arr = a;
int c = 1, maxcount = 1, maxvalue = 0;
int result = 0;
for (int i = 0; i < arr.Length; i++)
{
maxvalue = arr[i];
for (int j = 0; j <arr.Length; j++)
{
if (maxvalue == arr[j] && j != i)
{
c++;
if (c > maxcount)
{
maxcount = c;
result = arr[i];
}
}
else
{
c=1;
}
}
}
return result;
}

Maybe O(n log n), but fast:
sort the array a[n]
// assuming n > 0
int iBest = -1; // index of first number in most popular subset
int nBest = -1; // popularity of most popular number
// for each subset of numbers
for(int i = 0; i < n; ){
int ii = i; // ii = index of first number in subset
int nn = 0; // nn = count of numbers in subset
// for each number in subset, count it
for (; i < n && a[i]==a[ii]; i++, nn++ ){}
// if the subset has more numbers than the best so far
// remember it as the new best
if (nBest < nn){nBest = nn; iBest = ii;}
}
// print the most popular value and how popular it is
print a[iBest], nBest

Yet another solution with linq:
static int[] GetMostCommonIntegers(int[] nums)
{
return nums
.ToLookup(n => n)
.ToLookup(l => l.Count(), l => l.Key)
.OrderBy(l => l.Key)
.Last()
.ToArray();
}
This solution can handle case when several numbers have the same number of occurences:
[1,4,5,7,1] => [1]
[1,1,2,2,3,4,5] => [1,2]
[6,6,6,2,2,1] => [6]

Related

Which iterator(other than for, foreach) can be used to count the number of character in a string?

I dont know what iteration method to be used for more efficiency, Here i have listed my solution which i have tried. is there any other way to iterate, i mean any special methods or ways?
Method One :
Here i have used two for loops so the iteration goes for 2N times
public void CountChar()
{
String s = Ipstring();
int[] counts = new int[256];
char[] c = s.ToCharArray();
for (int i = 0; i < c.Length; ++i)
{
counts[c[i]]++;
}
for (int i = 0; i < c.Length; i++)
{
Console.WriteLine(c[i].ToString() + " " + counts[c[i]]);
Console.WriteLine();
}
}
Method 2 :
public void CountChar()
{
_inputWord = Ipstring();
char[] test = _inputWord.ToCharArray();
char temp;
int count = 0, tcount = 0;
Array.Sort(test);
int length = test.Length;
temp = test[0];
while (length > 0)
{
for (int i = 0; i < test.Length; i++)
{
if (temp == test[i])
{
count++;
}
}
Console.WriteLine(temp + " " + count);
tcount = tcount + count;
length = length - count;
count = 0;
if (tcount != test.Length)
temp = test[tcount];
//atchutharam. aaachhmrttu
}
}
Method three:
public void CountChar()
{
int indexcount = 0;
s = Ipstring();
int[] count = new int[s.Length];
foreach (char c in s)
{
Console.Write(c);
count[s.IndexOf(c)]++;
}
foreach (char c in s)
{
if (indexcount <= s.IndexOf(c))
{
Console.WriteLine(c);
Console.WriteLine(count[s.IndexOf(c)]);
Console.WriteLine("");
}
indexcount++;
////atchutharam
}
}
You can use LINQ methods to group the characters and count them:
public void CountChar() {
String s = Ipstring();
foreach (var g in s.GroupBy(c => c)) {
Console.WriteLine("{0} : {1}", g.Key, g.Count());
}
}
Your loops are not nested so your complexity is not N*N (O(n^2)) but 2*N which gives O(N) because you can always ignore constants :
for(){}
for(){} // O(2N) = O(N)
for()
{
for(){}
} // O(N*N) = O(N^2)
If you really want to know which one of these 3 solutions have the fastest execution time in a specific environment, do a benchmark.
If you want the one that is the most clean and readable (And you should almost always aim for that), just use LINQ :
String s = Ipstring();
int count = s.Count();
It will execute in O(N) too.
If you need the results in arrays:
var groups = s.GroupBy(i => i ).OrderBy( g => g.Key );
var chars = groups.Select(g => g.Key).ToArray();
var counts = groups.Select(g => g.Count()).ToArray();
Otherwise:
var dict = s.GroupBy(i => i).ToDictionary(g => g.Key, g => g.Count());
foreach (var g in dict)
{
Console.WriteLine( "{0}: {1}", g.Key, g.Value );
}

search equals width LINQ

I have a generic list of lists, trying to determine if there are already five equal numbers in each list.
If not find equals in lists, then add list into lists
this code work but I like learn more about linq.
how can do this using LINQ.
thank you
private void button2_Click(object sender, EventArgs e)
{
int n1 = (int)numericUpDown1.Value;
int n2 = (int)numericUpDown2.Value;
int n3 = (int)numericUpDown3.Value;
int n4 = (int)numericUpDown4.Value;
int n5 = (int)numericUpDown5.Value;
int n6 = (int)numericUpDown6.Value;
int n7 = (int)numericUpDown7.Value;
int n8 = (int)numericUpDown8.Value;
int n9 = (int)numericUpDown9.Value;
int n10 = (int)numericUpDown10.Value;
int n11 = (int)numericUpDown11.Value;
int n12 = (int)numericUpDown12.Value;
list = new List<int>();
list.Add(n1);
list.Add(n2);
list.Add(n3);
list.Add(n4);
list.Add(n5);
list.Add(n6);
list.Add(n7);
list.Add(n8);
list.Add(n9);
list.Add(n10);
list.Add(n11);
list.Add(n12);
if (data.Count == 0)
data.Add(list);
else
{
int l = data.Count;
bool eq =false;
for (int i = 0; i < l; i++)
{
int count = 0;
foreach (int n in list)
{
if (data[i].IndexOf(n) != -1)
++count;
if (count == 5)
{
eq = true;
break;
}
}
if (eq == true)
break;
}
if (eq == false)
data.Add(list);
else
{
// do nothing
}
}
}
you could use Intersect and Count extension methods.
something like
var exist = false;
foreach (var existingList in data) {
if (existingList.Intersect(list).Count() >=5) {
exist = true;
break;
}
if (!exist) data.Add(list);
But depending on the size of your lists, this will be far less performant, as the "check for intersects >= 5" will intersect all data of the lists.
trying to determine if there are already five equal numbers in each list. If not, then add them into lists
You can combine Enumerable.Count and loops, for example:
int n1 = (int)numericUpDown1.Value;
foreach(List<int> list in data)
{
int count = list.Count(i => i == n1);
while(count++ < 5)
list.Add(n1);
}
[EDIT] - please see the [UPDATE] below
I believe that your current code should look like:
...
int count = 0;
for (int i = 0; i < l; i++)
{
//int count = 0;
foreach (int n in list)
{
...
Anyway, to answer your question (if I understood correctly what you want to achieve) you may use this:
class Program
{
static List<List<int>> data;
static List<int> list;
static void Main(string[] args)
{
data = new List<List<int>>();
for (int i = 0; i < 6; i++)
{
list = new List<int>();
list.Add(1);
list.Add(2);
list.Add(1);
var result = data
.Union(new[]{list})
.SelectMany(j => j)
.GroupBy(j => j)
.Select(j => new { j.Key, j })
.Where(j => j.j.Count() > 4);
if (result.Count() == 0)
data.Add(list);
}
}
}
[UPDATE]
Ok, I think I understood what you want to achieve: if there are no other lists in data that have at least 5 elements in common with the list, the list should be added to the data, which is a List<List<int>>.
var result = data.Any(i => i.Intersect(list).Count() > 4);
if(!result)
data.Add(list);
Given your code you've posted, I think the solution is:
List<int> list = new List<int>();
List<List<int>> data = new List<List<int>>();
if (data.All(l => l.Intersect(list).Count() < 5))
data.Add(list);

Obtain the index of the maximum element

Given such a list:
List<int> intList = new List<int>();
intList.Add(5);
intList.Add(10);
intList.Add(15);
intList.Add(46);
how do you obtain the index of the maximum element in the list? In this case, it's at index 3.
Edit: It's a shame that standard LINQ doesn't ship this functionalities.
this way :
var maxIndex = foo.IndexOf(foo.Max());
Here is a simple* and relatively efficient** solution:
int indexMax
= !intList.Any() ? -1 :
intList
.Select( (value, index) => new { Value = value, Index = index } )
.Aggregate( (a, b) => (a.Value > b.Value) ? a : b )
.Index;
The !intList.Any() ? -1 : will force a -1 if the list is empty;
The Select will project each int element into an anonymous type with two properties: Value and Index;
The Aggregate will get the element with the highest Value;
Finally, we get the Index of the chosen element.
* Simplicity is relative. The aim here was to reach a balance of readability and still only scan the list once.
** The allocation of lots of new objects during the Select is probably wasteful. As some people tested, it doesn't perform well for large lists.
EDIT 1: empty list check added.
EDIT 2: added caveats about performance.
Here's a custom LINQ method which I believe does what you want. (I previously had another which does a projection, but you can just call Select to do that, as you only need the index.)
public static int MaxIndex<T>(this IEnumerable<T> source)
{
IComparer<T> comparer = Comparer<T>.Default;
using (var iterator = source.GetEnumerator())
{
if (!iterator.MoveNext())
{
throw new InvalidOperationException("Empty sequence");
}
int maxIndex = 0;
T maxElement = iterator.Current;
int index = 0;
while (iterator.MoveNext())
{
index++;
T element = iterator.Current;
if (comparer.Compare(element, maxElement) > 0)
{
maxElement = element;
maxIndex = index;
}
}
return maxIndex;
}
}
Here's how to do it in one (long) line using LINQ, with just a single pass through the collection. It should work for any IEnumerable<int>, not just lists.
int maxIndex = intList
.Select((x, i) => new { Value = x, Index = i })
.Aggregate
(
new { Value = int.MinValue, Index = -1 },
(a, x) => (a.Index < 0) || (x.Value > a.Value) ? x : a,
a => a.Index
);
Here's the non-LINQ equivalent of the above, using a foreach loop. (Again, just a single pass through the collection, and should work for any IEnumerable<int>.)
int maxIndex = -1, maxValue = int.MinValue, i = 0;
foreach (int v in intList)
{
if ((maxIndex < 0) || (v > maxValue))
{
maxValue = v;
maxIndex = i;
}
i++;
}
If you know that the collection is an IList<int> then a plain for loop is probably the easiest solution:
int maxIndex = -1, maxValue = int.MinValue;
for (int i = 0; i < intList.Count; i++)
{
if ((maxIndex < 0) || (intList[i] > maxValue))
{
maxValue = intList[i];
maxIndex = i;
}
}
I can't improve on Jon Skeet's answer for the general case, so I am going for the 'high performance' prize in the specific case of a list of ints.
public static class Extensions
{
public static int IndexOfMaximumElement(this IList<int> list)
{
int size = list.Count;
if (size < 2)
return size - 1;
int maxValue = list[0];
int maxIndex = 0;
for (int i = 1; i < size; ++i)
{
int thisValue = list[i];
if (thisValue > maxValue)
{
maxValue = thisValue;
maxIndex = i;
}
}
return maxIndex;
}
Here is my solution:
public static int IndexOfMax(this IList<int> source)
{
if (source == null)
throw new ArgumentNullException("source");
if (source.Count == 0)
throw new InvalidOperationException("List contains no elements");
int maxValue = source[0];
int maxIndex = 0;
for (int i = 1; i < source.Count; i++)
{
int value = source[i];
if (value > maxValue)
{
maxValue = value;
maxIndex = i;
}
}
return maxIndex;
}
Here's the non-linq method if you like:
private int ReturnMaxIdx(List<int> intList)
{
int MaxIDX = -1;
int Max = -1;
for (int i = 0; i < intList.Count; i++)
{
if (i == 0)
{
Max = intList[0];
MaxIDX = 0;
}
else
{
if (intList[i] > Max)
{
Max = intList[i];
MaxIDX = i;
}
}
}
return MaxIDX;
}
This is a single pass through the list at least.
Hope this helps,
Kyle
Use a custom function, using Max() and IndexOf() cost more.

How to get all subsets of an array?

Given an array: [dog, cat, mouse]
what is the most elegant way to create:
[,,]
[,,mouse]
[,cat,]
[,cat,mouse]
[dog,,]
[dog,,mouse]
[dog,cat,]
[dog,cat,mouse]
I need this to work for any sized array.
This is essentially a binary counter, where array indices represent bits. This presumably lets me use some bitwise operation to count, but I can't see a nice way of translating this to array indices though.
Elegant? Why not Linq it.
public static IEnumerable<IEnumerable<T>> SubSetsOf<T>(IEnumerable<T> source)
{
if (!source.Any())
return Enumerable.Repeat(Enumerable.Empty<T>(), 1);
var element = source.Take(1);
var haveNots = SubSetsOf(source.Skip(1));
var haves = haveNots.Select(set => element.Concat(set));
return haves.Concat(haveNots);
}
string[] source = new string[] { "dog", "cat", "mouse" };
for (int i = 0; i < Math.Pow(2, source.Length); i++)
{
string[] combination = new string[source.Length];
for (int j = 0; j < source.Length; j++)
{
if ((i & (1 << (source.Length - j - 1))) != 0)
{
combination[j] = source[j];
}
}
Console.WriteLine("[{0}, {1}, {2}]", combination[0], combination[1], combination[2]);
}
You can use the BitArray class to easily access the bits in a number:
string[] animals = { "Dog", "Cat", "Mouse" };
List<string[]> result = new List<string[]>();
int cnt = 1 << animals.Length;
for (int i = 0; i < cnt; i++) {
string[] item = new string[animals.Length];
BitArray b = new BitArray(i);
for (int j = 0; j < item.Length; j++) {
item[j] = b[j] ? animals[j] : null;
}
result.Add(item);
}
static IEnumerable<IEnumerable<T>> GetSubsets<T>(IList<T> set)
{
var state = new BitArray(set.Count);
do
yield return Enumerable.Range(0, state.Count)
.Select(i => state[i] ? set[i] : default(T));
while (Increment(state));
}
static bool Increment(BitArray flags)
{
int x = flags.Count - 1;
while (x >= 0 && flags[x]) flags[x--] = false ;
if (x >= 0) flags[x] = true;
return x >= 0;
}
Usage:
foreach(var strings in GetSubsets(new[] { "dog", "cat", "mouse" }))
Console.WriteLine(string.Join(", ", strings.ToArray()));
Guffa's answer had the basic functionality that I was searching, however the line with
BitArray b = new BitArray(i);
did not work for me, it gave an ArgumentOutOfRangeException. Here's my slightly adjusted and working code:
string[] array = { "A", "B", "C","D" };
int count = 1 << array.Length; // 2^n
for (int i = 0; i < count; i++)
{
string[] items = new string[array.Length];
BitArray b = new BitArray(BitConverter.GetBytes(i));
for (int bit = 0; bit < array.Length; bit++) {
items[bit] = b[bit] ? array[bit] : "";
}
Console.WriteLine(String.Join("",items));
}
Here's a solution similar to David B's method, but perhaps more suitable if it's really a requirement that you get back sets with the original number of elements (even if empty):.
static public List<List<T>> GetSubsets<T>(IEnumerable<T> originalList)
{
if (originalList.Count() == 0)
return new List<List<T>>() { new List<T>() };
var setsFound = new List<List<T>>();
foreach (var list in GetSubsets(originalList.Skip(1)))
{
setsFound.Add(originalList.Take(1).Concat(list).ToList());
setsFound.Add(new List<T>() { default(T) }.Concat(list).ToList());
}
return setsFound;
}
If you pass in a list of three strings, you'll get back eight lists with three elements each (but some elements will be null).
Here's an easy-to-follow solution along the lines of your conception:
private static void Test()
{
string[] test = new string[3] { "dog", "cat", "mouse" };
foreach (var x in Subsets(test))
Console.WriteLine("[{0}]", string.Join(",", x));
}
public static IEnumerable<T[]> Subsets<T>(T[] source)
{
int max = 1 << source.Length;
for (int i = 0; i < max; i++)
{
T[] combination = new T[source.Length];
for (int j = 0; j < source.Length; j++)
{
int tailIndex = source.Length - j - 1;
combination[tailIndex] =
((i & (1 << j)) != 0) ? source[tailIndex] : default(T);
}
yield return combination;
}
}
This is a small change to Mehrdad's solution above:
static IEnumerable<T[]> GetSubsets<T>(T[] set) {
bool[] state = new bool[set.Length+1];
for (int x; !state[set.Length]; state[x] = true ) {
yield return Enumerable.Range(0, state.Length)
.Where(i => state[i])
.Select(i => set[i])
.ToArray();
for (x = 0; state[x]; state[x++] = false);
}
}
or with pointers
static IEnumerable<T[]> GetSubsets<T>(T[] set) {
bool[] state = new bool[set.Length+1];
for (bool *x; !state[set.Length]; *x = true ) {
yield return Enumerable.Range(0, state.Length)
.Where(i => state[i])
.Select(i => set[i])
.ToArray();
for (x = state; *x; *x++ = false);
}
}
I'm not very familiar with C# but I'm sure there's something like:
// input: Array A
foreach S in AllSubsetsOf1ToN(A.Length):
print (S.toArray().map(lambda x |> A[x]));
Ok, I've been told the answer above won't work. If you value elegance over efficiency, I would try recursion, in my crappy pseudocode:
Array_Of_Sets subsets(Array a)
{
if (a.length == 0)
return [new Set();] // emptyset
return subsets(a[1:]) + subsets(a[1:]) . map(lambda x |> x.add a[0])
}
Here is a variant of mqp's answer, that uses as state a BigInteger instead of an int, to avoid overflow for collections containing more than 30 elements:
using System.Numerics;
public static IEnumerable<IEnumerable<T>> GetSubsets<T>(IList<T> source)
{
BigInteger combinations = BigInteger.One << source.Count;
for (BigInteger i = 0; i < combinations; i++)
{
yield return Enumerable.Range(0, source.Count)
.Select(j => (i & (BigInteger.One << j)) != 0 ? source[j] : default);
}
}
Easy to understand version (with descriptions)
I assumed that source = {1,2,3,4}
public static IEnumerable<IEnumerable<T>> GetSubSets<T>(IEnumerable<T> source)
{
var result = new List<IEnumerable<T>>() { new List<T>() }; // empty cluster added
for (int i = 0; i < source.Count(); i++)
{
var elem = source.Skip(i).Take(1);
// for elem = 2
// and currently result = [ [],[1] ]
var matchUps = result.Select(x => x.Concat(elem));
//then matchUps => [ [2],[1,2] ]
result = result.Concat(matchUps).ToList();
// matchUps and result concat operation
// finally result = [ [],[1],[2],[1,2] ]
}
return result;
}
The way this is written, it is more of a Product (Cartesian product) rather than a list of all subsets.
You have three sets: (Empty,"dog"), (Empty,"cat"),(Empty,"mouse").
There are several posts on general solutions for products. As noted though, since you really just have 2 choices for each axis a single bit can represent the presence or not of the item.
So the total set of sets is all numbers from 0 to 2^N-1. If N < 31 an int will work.

How to check number of pairs elements in array?

I am trying to solve a problem but I can't seem to figure out the right way to do it. For example: array []= {1,1,1,1,1,2,3,3,4} . Here pairs of 1 are 2 and a pair of 3 is 1. So total there is 3 pair. I am trying to solve this. Here is the current code situation.
static int PairCounter(int n, int[] ar) {
int temp_n = 0;
//store the array range with constrains
Console.WriteLine("Enter the number of object: ");
temp_n = Console.Convert.ToInt32(Console.ReadLine());
if((temp_n >= 1) || (temp_n <= 100)){
n = temp_n;
}else{
Console.WriteLine("Please enter a value less then 100 and greater then 1.");
temp_n = Console.Convert.ToInt32(Console.ReadLine());
if((temp_n >= 1) || (temp_n <= 100)){
n = temp_n;
}else{
Console.WriteLine("Please rerun the code.");
}
}
//Stores Array with constrains
Console.WriteLine("Enter the number of array: ");
int[] arr = new int[n];
for(int i = 0; i<= n; i++){
arr[i] = Console.Convert.ToInt32(Console.ReadLine());
if((arr[i] >= 1) || (arr[i] <= 100)){
ar[i] = arr[i];
}else{
Console.WriteLine("Please enter a value less then 100 and greater then 1.");
arr[i] = Convert.ToInt32(Console.ReadLine());
if((arr[i] >= 1) || (arr[i] <= 100)){
ar[i] = arr[i];
}else{
Console.WriteLine("Rerun the code");
}
}
}
//copy the array to another array
int[] array3 = new int[n];
for(i=0;i<=n; i++)
{
array3[i]=ar[i];
}
int repeat_counter = 0;
for(int i = 0; i<=n;i++){
if(ar[i].Contains(array3[i])){
repeat_counter++;
}
}
}
Any help is appreciatable.
You can do this in a one liner:
var pairs = ii.GroupBy(i => i).Sum(g => g.Count() / 2);
But yeah, using linq is cheating in the present circumstances. An easy way to solve this is taking advantage that you are counting ints. You can use an array to keep track of how many instances of any given number you find by using that same number as the index:
static int CountPairs(int[] array)
{
var counter = new int[array.Length];
foreach (var i in array)
{
counter[i] += 1;
}
var pairs = 0;
foreach (var count in counter)
{
pairs += count / 2;
}
return pairs;
}
That should also do the trick.
Of course you could generalize this to work with anything, but a simple array won't work anymore, you'd need something a tad more sophisticated: a dictionary. But the idea is the same as the previous solution; simply keeping track of how many times you see any given item:
static int CountPairs<T>(IEnumerable<T> source)
{
var counter = new Dictionary<T, int>();
foreach (var item in source)
{
if (!counter.TryAdd(item, 1))
counter[item] += 1;
}
var pairs = 0;
foreach (var count in counter.Values)
{
pairs += count / 2;
}
return pairs;
}
But...meh, once here, its probably better to simply use the linq one-liner ;)
with Linq its very simple:
var result = array.GroupBy(x => x).Select(x => new {num = x.Key, count = x.Count() / 2});
foreach(var item in result)
Consolve.WriteLine($"{item.count} pair(s) of {item.num}");
To get the total number of pairs:
int total = array.GroupBy(x => x).Sum(x => x.Count());
Consolve.WriteLine($"{total} pair(s) in total");

Categories