Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I have an array: options[15,12,52,a,12,15,abc,15] and I need to count options.
Example:
counts[15]:3 or counts[12]:2 ...
I need this in C#. How can I do this?
Thank you for your answers. My solution is here:
Dictionary<object, int> counts = new Dictionary<object, int>();
for (var t = 0; t < voters_options.GetLength(0); t++) {
if (voters_options[t] != null) {
if (!counts.ContainsKey(voters_options[t]))
counts[voters_options[t]] = 1;
else
counts[voters_options[t]] = 1 + counts[voters_options[t]];
}
}
For C# begginer:
using System;
using System.Collections.Generic;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
object[] options = { 15, 12, 52, "a", 12, 15, "abc", 15 };
Dictionary<object, int> counts = new Dictionary<object, int>();
for (var t = 0; t < options.GetLength(0); t++)
{
if (!counts.ContainsKey(options[t]))
counts[options[t]] = 1;
else
counts[options[t]] = 1 + counts[options[t]];
}
foreach (var entry in counts)
Console.Out.WriteLine("Key: " + entry.Key + "; Count: " + entry.Value.ToString());
}
}
}
Results are:
Key: 15; Count: 3
Key: 12; Count: 2
Key: 52; Count: 1
Key: a; Count: 1
Key: abc; Count: 1
You can use LINQ grouping:
string[] options = { "15", "12", "52", "a", "12", "15", "abc", "15" };
var groupedOptions = options.GroupBy(o => o)
.ToDictionary(g => g.Key, g => g.Count());
foreach (var groupedOption in groupedOptions)
Console.WriteLine("{0} : {1}", groupedOption.Key, groupedOption.Value);
Try this with linq in c#:
var groups = arr1.GroupBy(item => item);
foreach (var group in groups)
{
Console.WriteLine(string.Format("{0} occurences of {1}", group.Count(), group.Key);
}
Counting occurrences in Array
Here's a traditional approach.
var options = new [] {"15","12","52","a","12","15","abc","15"};
Dictionary<string, int> counts = new Dictionary<string, int>();
foreach(var t in options)
{
if(counts.ContainsKey(t))
counts[t]++;
else
counts[t] = 1;
}
You can use a dictionary to count the elements.
public ConcurrentDictionary<string, int> CountOptions(int[] options)
{
ConcurrentDictionary<string, int> counts = new ConcurrentDictionary<string, int>();
for (var t = 0; t < options.Length; t++)
{
counts.AddOrUpdate(options[t].ToString(), 1, (k, v) => v + 1);
}
return counts;
}
Related
I'm facing an issue while displaying multiple lists the value in a single row column.
Here is an example of code.
public class Program
{
static void Main(string[] args)
{
Dictionary<string, List<object>> keyvalues = new Dictionary<string, List<object>>();
keyvalues.Add("Code", new List<object>() { 1, 2, 3, 4 });
keyvalues.Add("Name", new List<object>() { "A", "B", "C", "D" });
keyvalues.Add("Age", new List<object>() { 20, 30, 40, 50 });
var listData = keyvalues.Select(x => x.Value).Select((x, i) => new { obj = x, index = i });
var listData = keyvalues.Select((x, iparent) => x.Value.Select((z, i) => new { value = string.Concat(z, x.Value[i]) }).ToList()).ToList();
Console.ReadLine();
}
}
Expected output
1A20
2B30
3C40
4D50
If you are using .Net 6, you could make use of the new 3 way Zip extension.
var result = keyvalues["Code"].Zip(keyvalues["Name"], keyvalues["Age"])
.Select(x=> $"{x.First}{x.Second}{x.Third}");
Why make it so complicated?
for(int x = 0; x<keyValues["Code"].Count; x++)
Console.WriteLine(
keyValues["Code"][x]+
keyValues["Name"][x]+
keyValues["Age"][x]
);
LINQ's a hammer; not every problem is a nail.
ps if you have N keys, you can easily turn it into a
var keys = new[]{"Code","Name","Age","Foo","Bar"};
for(...)
foreach(var k in keys)
... //some concat here or use the values directly eg adding to your page
You could easily use Zip here. However, you could roll your own
public static IEnumerable<string> DoStuff<T, T2>(Dictionary<T, List<T2>> source)
{
var max = source.Values.Max(x => x?.Count ?? 0);
for (var i = 0; i < max; i++)
yield return string.Concat(source.Values.Select(x => x.ElementAtOrDefault(i)));
}
Usage
var results = DoStuff(keyvalues);
Console.WriteLine(string.Join(Environment.NewLine,results));
Output
1A20
2B30
3C40
4D50
or
public static IEnumerable<string> DoStuff<T>(List<T>[] source)
{
var max = source.Max(x => x?.Count ?? 0);
for (var i = 0; i < max; i++)
yield return string.Concat(source.Select(x => x.ElementAtOrDefault(i)));
}
...
var results = DoStuff(keyvalues.Values.ToArray());
Console.WriteLine(string.Join(Environment.NewLine,results));
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I wish I could use this code with strings instead of integers
public static List<int> EvenlyDistribute(List<int> list)
{
List<int> original = list;
Dictionary<int, int> dict = new Dictionary<int, int>();
list.ForEach(x => dict[x] = dict.Keys.Contains(x) ? dict[x] + 1 : 1);
list = list.Where(x => dict[x] == 1).ToList();
foreach (int key in dict.Where(x => x.Value > 1).Select(x => x.Key))
{
int iterations = original.Where(x => x == key).Count();
for (int i = 0; i < iterations; i++)
list.Insert((int)Math.Ceiling((decimal)((list.Count + iterations) / iterations)) * i, key);
}
return list;
}
Usage in main:
List<int> test = new List<int>() {11,11,11,13,14,15,16,17,18,19,19,19,19};
List<int> newList = EvenlyDistribute(test);
Output:
19,11,13,19,14,11,19,15,16,19,11,17,18
is it possible to use this method but using strings?
You can replace int with a generic type and replace the == with .Equals so that it will work with any type (including strings):
public static List<T> EvenlyDistribute<T>(List<T> input)
{
if (input == null || input.Count < 3) return input;
var dict = input.Distinct().ToDictionary(
key => key, value => input.Count(x => x.Equals(value)));
input = input.Where(x => dict[x] == 1).ToList();
foreach (var kvp in dict.Where(item => item.Value > 1))
{
decimal count = kvp.Value;
for (var i = 0; i < count; i++)
{
input.Insert((int) (Math.Ceiling((input.Count + count) / count) * i),
kvp.Key);
}
}
return input;
}
Try following :
class Program
{
static void Main(string[] args)
{
List<int> test = new List<int>() { 11, 11, 11, 13, 14, 15, 16, 17, 18, 19, 19, 19, 19 };
List<int> newList = EvenlyDistribute(test);
}
static List<int> EvenlyDistribute(List<int> input)
{
List<int> results = new List<int>();
var groups = input.GroupBy(x => x).OrderByDescending(x => x.Count());
int max = groups.First().Count();
for (int i = max - 1; i >= 0; i--)
{
foreach (var group in groups)
{
if (group.Count() - 1 >= i)
{
results.Add(group.Skip(i - 1).First());
}
}
}
return results;
}
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have a list something like that
var x = new List<string>{"A","B","C","D","E","F"};
I want to group it in doubles like that
1-A
1-B
2-C
2-D
3-E
3-F
What my solution is
var result = new Dictionary<int, List<string>>();
var sequence = 1;
var groupList = new List<string>();
for (var i = 0; i < x.Length ; i++)
{
groupList.Add(x[i]);
if ((i + 1)%2 == 0)
{
result.Add(sequence, groupList);
groupList = new List<string>();
sequence++;
}
}
return result;
I am looking for alternative (better) ways to get same result.
Here is another way:
int numPairs = 3;
char[] abc = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
var dict = new Dictionary<int, char[]>();
for (int i = 1, k=1; i <= numPairs && k<abc.Length; i++, k+=2)
{
dict.Add(i, new char[] { abc[k - 1], abc[k] });
}
return dict;
This will do the same.
var y = x.GroupBy(i =>Convert.ToInt32((x.IndexOf(i) + 1.1) * 0.5));
I think this is a readable Linq solution:
var result = x
.Select((value, index) => new { value, index })
.GroupBy(arg => arg.index / 2 + 1, arg => arg.value);
The Select projects the value with its index into an anonymous type, and the GroupBy groups by the index.
If you need the groupings in a Dictionary like in your question, use ToDictionary:
var dictionary = result.ToDictionary(
grouping => grouping.Key,
grouping => grouping.ToList());
I'm trying to convert a simple piece of Math to Linq.
I want to bundle together the prime factors for several numbers into one collection.
Consider the following integers.
8 = 2 * 2 * 2
12 = 2 * 2 * 3
The smallest number divisible by both 8 & 12 is 24, so I'd like the resultant group to contain
{ 2, 2, 2, 3 }
If I use Concat the result is {2,2,2,2,2,3} - not correct
If I use Union the result is {2,3} - not correct
Is there a built in Linq Set Manipulation function which will recognise that it needs to keep the maximum number of occurences of an item (i.e. not add another if there are already enough there to satisfy if & add another if there aren't)
Well, it's not any existing function, as I don't think such exists, but pretty simple code is capable of handling this:
var listA = new List<int> {2, 2, 2};
var listB = new List<int> {2, 2, 3};
var grouppedA = listA.GroupBy(i => i).Select(g => new { key = g.Key, count = g.Count()});
var grouppedB = listB.GroupBy(i => i).Select(g => new { key = g.Key, count = g.Count()});
var result = grouppedA
.Union(grouppedB)
.GroupBy(g => g.key)
.SelectMany(g => Enumerable.Repeat(g.Key, g.Max(h => h.count)));
foreach (int i in result)
{
Console.Write(i + " ");
}
Console.ReadKey();
Output:
2 2 2 3
using System;
using System.Collections.Generic;
public class Sample {
public static void Main(String[] args) {
var n8 = toFactors(8);
var n12 = toFactors(12);
var uf = unionFactors(n8, n12);//LCM
printFactors(uf);
}
public static void printFactors(Dictionary<long, int> factors){
Console.Write("{ ");
foreach(var factor in factors.Keys){
for(int i=0;i<factors[factor];++i)
Console.Write( factor + " ");
}
Console.WriteLine("}");
}
public static Dictionary<long, int> unionFactors(Dictionary<long, int> af, Dictionary<long, int> bf){
Dictionary<long, int> uf = new Dictionary<long, int>();
foreach(var kv in af){
uf.Add(kv.Key, kv.Value);//copy
}
foreach(var kv in bf){
if(uf.ContainsKey(kv.Key)){
if(kv.Value > uf[kv.Key])//max
uf[kv.Key] = kv.Value;
} else {
uf.Add(kv.Key, kv.Value);
}
}
return uf;
}
public static Dictionary<long, int> toFactors(long num){
var factors = new Dictionary<long, int>();
long n = num, i = 2, sqi = 4;
while(sqi <= n){
while(n % i == 0){
n /= i;
if(factors.ContainsKey(i)){
factors[i] += 1;
} else {
factors.Add(i, 1);
}
}
sqi += 2 * (i++) + 1;
}
if(n != 1 && n != num){
if(factors.ContainsKey(i)){
factors[i] += 1;
} else {
factors.Add(i, 1);
}
}
if(factors.Count == 0)
factors.Add(num, 1);//prime
return factors;
}
}
I have a dict<string, list<string>>, say 3 keys in dict, the first key has 2 values, the secodn 3 values, the third key has 3 values. If I get a value from each value set, then I will have a combination of 2*3*3 = 18 sets
How to code in c#?
thanks
Edit
Sorry did not make it clear
I want something like this
say I have dict like this
{"1",new List<String>(){"a", "b"}},
{"2",new List<String>(){"c", "d", "e"}},
{"3", new List<string>() {"f", "g"}
I want output like this
acf, acg, adf, adg, aef, aeg
bcf, bcg, bdf, bdg, bef, beg
With Linq:
var dict = new Dictionary<String, List<String>>() {
{"1",new List<String>(){"a", "b"}},
{"2",new List<String>(){"c", "d", "e"}},
{"3",new List<String>(){"f", "g", "h"}},
};
var combis = from kv in dict
from val1 in kv.Value
from val2 in kv.Value
select string.Format("{0}{1}", val1, val2);
foreach (var combi in combis)
Console.WriteLine(combi);
demo: http://ideone.com/nm7mY
Quick & dirty but you may polish this method. The result list contains expected result:
Usage:
var dict = new Dictionary<String, List<String>>() {
{"1",new List<String>(){"a", "b"}},
{"2",new List<String>(){"c", "d", "e"}},
{"3",new List<String>(){"f", "g"}},
};
var collections = dict.Select(kvp => kvp.Value).ToArray();
var result = new List<string>();
GetNextProduct(collections, 0, String.Empty, result);
Method that produces the result:
private static void GetNextProduct(IEnumerable<string>[] collections, int collectionIndex, string currentProduct, IList<string> results)
{
var currentList = collections[collectionIndex];
bool isLast = collections.Length == collectionIndex + 1;
foreach (var s in currentList)
{
if (isLast) results.Add(currentProduct + s);
else GetNextProduct(collections, collectionIndex + 1, currentProduct + s, results);
}
}
I think you mean this?
Dictionary<string, int> dict = new Dictionary<string, int>
{
{ "Hello World", 1 },
{ "HelloWorld", 1 },
{ "Hello World", 1 },
};
foreach (var item in dict) // var is of type KeyValuePair<string, int>
Console.WriteLine(item.Key + ", " + item.Value);
Dictionary<string, List<int>> storage = new Dictionary<string, List<int>>();
storage.Add("key1", new List<int>() { 2, 7 });
storage.Add("key2", new List<int>() { 8, 4, 1});
storage.Add("key3", new List<int>() { 3, 9, 3 });
foreach (string key in storage.Keys)
{
//access to single storage...
List<int> subStorage = (List<int>)storage[key];
foreach (int item in subStorage)
{
//access to single value inside storage...
}
}
I would try something like the following if I was trying to read or edit the values in the lists:
Dictionary<int, List<string>> dict = new Dictionary<int, List<string>>();
var arrayOfValues = dict.Values.ToArray();
for (int i = 0; i < arrayOfValues.Length; i++)
{
for (int j = 0; j < arrayOfValues[i].Count; j++)
{
//read/edit arrayOfValues[i][j];
}
}
You do not need recursion since you know the dept of the "tree".