I initialize a dictionary with n keys and zero values. By parameter I can setup some values.
When calling the constructor I execute this
public Store(Dictionary<int, int> initialItems = null)
{
items = new Dictionary<int, int>();
for (int i = 0; i < 45; i++) // 45 items should exist
{
int initialAmount = 0; // 0 as starting value
if (initialItems != null) // parameter is passed in?
{
initialItems.TryGetValue(i, out initialAmount); // start with a higher value than 0
}
items.Add(i, initialAmount); // initialize value with 0 or more
}
}
private Dictionary<int, int> items;
I'm asking if this is a good way of passing starting values by parameter. I just want to create a bunch of items and set the value to 0 or a higher value if specified somewhere else, as a constructor parameter for example.
You can also pass initial dictionary to dictionary's constructor like this:
public Store(Dictionary<int, int> initialItems = null)
{
if (initialItems!=null)
items = new Dictionary<int, int>(initialItems);
else
items = new Dictionary<int, int>();
for (int i = 0; i < 45; i++) // 45 items should exist
{
if (!items.ContainsKey(i))
items.Add(i, 0); // initialize value with 0
}
}
private Dictionary<int, int> items;
Related
Please check the code below. I am trying to set value to a random property of a int list. Problem is that even after i set 5 to a random list this value getting inserted to that property. What am I doing wrong here?
var TransactionList = new List<int>();
for (int i = 0; i < 59; i++)
{
TransactionList.Add(0);
}
var randTransaction = TransactionList.OrderBy(x => Guid.NewGuid()).FirstOrDefault();
//here i am trying to set 5 value to a random TrnasactionList but this not being set
randTransaction = 5;
Try like below. new Random().Next(0, 59); will return value between 0 and 59. Or you can better set it like new Random().Next(0, TransactionList.Count); for it to be dynamic with list.
new Random().Next(minValue, maxValue); The maxValue for the upper-bound in the Next() method is exclusive—the range includes minValue, maxValue-1, and all numbers in between.
var TransactionList = new List<int>();
for (int i = 0; i < 59; i++)
{
TransactionList.Add(0);
}
// var index = new Random().Next(0, 59);
// Below will work for dynamic length of list.
var index = new Random().Next(0, TransactionList.Count);
TransactionList[index] = 5;
If you don't mind the original list getting sorted you could do this:
class Program
{
static void Main(string[] args)
{
var transactionList = new List<int>();
for (int i = 0; i < 59; i++)
{
//I initialized the list with i instead of 0 to better see sorting in place
transactionList.Add(i);
}
transactionList.Sort(new RandomComparer());
//changed it to 99 to spot it more easily
transactionList[0] = 99;
foreach (var i in transactionList)
Console.WriteLine(i);
}
}
public class RandomComparer : IComparer<int>
{
private Random _random = new Random();
public int Compare(int x, int y)
{
return _random.Next(-1, 2);
}
}
See it in action:
https://dotnetfiddle.net/NKuPdx
randTransaction is "int" data type, which is primitive data type.
if you want to set randTransaction that reflect to it's object, just set the object it self
I want to use a Dictionary as the key of another Dictionary, but the comparision for equal keys shall not use the reference for comparision, but the Dictionary's content. How can I do this?
Here is what I currently have: I want to know how many equal histograms (implemented as Dictionary) I have. For that I create another Dictionary numberOfHistogramOccurences with the histograms as key, the value shall then be increased by one on each new addition of a histogram with equal content.
I am also open for hints on other ways of counting content-equal histograms/Dictionaries.
// define two histograms with equal content
Dictionary<int, int>[] histograms = new Dictionary<int, int>[2];
histograms[0] = new Dictionary<int, int>();
histograms[0][0] = 3;
histograms[0][5] = 1;
histograms[0][10] = 8;
histograms[1] = new Dictionary<int, int>();
histograms[1][0] = 3;
histograms[1][5] = 1;
histograms[1][10] = 8;
// use the equal histograms as key.
// as they are reference types, their reference is compared and not their content ):
var numberOfHistogramOccurences = new Dictionary<Dictionary<int, int>, int>();
foreach (var histogram in histograms)
{
if (!numberOfHistogramOccurences.ContainsKey(histogram))
numberOfHistogramOccurences[histogram] = 0;
numberOfHistogramOccurences[histogram]++;
}
// this gives two different keys;
// I need one key with a value of 2,
// as both histograms are equal
Debug.WriteLine("Number of different keys in numberOfHistogramOccurences: " + numberOfHistogramOccurences.Keys.Count);
Following my comment, using a custom comparer. Note that I added another histogram in order to check that it sees differences as well.
public static void Main()
{
// define two histograms with equal content
Dictionary<int, int>[] histograms = new Dictionary<int, int>[2];
histograms[0] = new Dictionary<int, int>();
histograms[0][0] = 3;
histograms[0][5] = 1;
histograms[0][10] = 8;
histograms[1] = new Dictionary<int, int>();
histograms[1][0] = 3;
histograms[1][5] = 1;
histograms[1][10] = 8;
histograms[2] = new Dictionary<int, int>();
histograms[2][0] = 1;
histograms[2][5] = 3;
histograms[2][10] = 8;
// use the equal histograms as key.
// as they are reference types, their reference is compared and not their content ):
/* change this line */
var numberOfHistogramOccurences = new Dictionary<Dictionary<int, int>, int>(new HistogramComparer());
/* ---------------- */
foreach (var histogram in histograms)
{
if (!numberOfHistogramOccurences.ContainsKey(histogram))
numberOfHistogramOccurences[histogram] = 0;
numberOfHistogramOccurences[histogram]++;
}
// this gives two different keys;
// I need one key with a value of 2,
// as both histograms are equal
Debug.WriteLine("Number of different keys in numberOfHistogramOccurences: " + numberOfHistogramOccurences.Keys.Count);
}
And the custom comparer class HistogramComparer:
public class HistogramComparer : IEqualityComparer<Dictionary<int, int>>
{
public bool Equals(Dictionary<int, int> x, Dictionary<int, int> y)
{
// check that y contains all x.Keys
foreach (var key in x.Keys)
if (!y.Keys.Contains(key))
return false;
// check that x contains all y.Keys
foreach (var key in y.Keys)
if (!x.Keys.Contains(key))
return false;
// check that keys have same values
foreach (var entry in x)
if (y[entry.Key] != entry.Value)
return false;
return true;
}
public int GetHashCode(Dictionary<int, int> obj)
{
int hash = 0;
foreach (var entry in obj)
hash ^= (entry.Key ^ entry.Value);
return hash;
}
}
I create a dictionary (Dictionary<string, bool> values).
I create the function:
private Dictionary<string, bool> ChangeValues(int line, Dictionary<string, bool> values)
{
for (int i = 0; i < line; i++)
{
}
return values;
}
I want to change bool values according the number of line.
The table below is the result of a dictionary (only show the bool):
line 0 = values["A"][false]
values["B"][false]
values["C"][false]
line 1 = values["A"][false]
values["B"][false]
values["C"][true]
line 2 = values["A"][false]
values["B"][true]
values["C"][false]
line n...
How I can change the bool value according the number of line?
Thanks.
[update]
After some help, the function is done:
private Dictionary<string, bool> ChangeValues(int line, Dictionary<string, bool> values)
{
string[] keys = values.Keys.ToArray();
keys = (from k in keys orderby k descending select k).ToArray();
for (int i = 0; i < line; i++)
{
for (int j = 0, bit = 1; j < values.Count; j++, bit <<= 1)
{
values[keys[j]] = (i & bit) != 0;
}
}
return values;
}
Thanks to PeterDuniho
If I understand the question correctly, all you want is to be able to iterate all possible combinations of the flags stored in your dictionary. In addition, these flags correspond exactly to the bits in your loop variable i.
If so, then you can just use the bits from the loop variable directly to set the flag values in the dictionary. For a general solution, you do need to pass the key names as well, in the correct order according to the bits you want to set.
For example:
private Dictionary<string, bool> ChangeValues(int line, Dictionary<string, bool> values, string[] keys)
{
for (int i = 0; i < line; i++)
{
for (int j = 0, bit = 1; j < keys.Length; j++, bit <<= 1)
{
values[keys[j]] = (i & bit) != 0;
}
// do something with values here
}
return values;
}
Call like this:
var result = ChangeValues(8, values, new [] { "C", "B", "A" });
Note that the above simply modifies the dictionary that was passed in. I infer from the way the question was asked — "I want to change bool values" — that this was your intent. However, if you actually want to return a whole new dictionary object, you can do so:
private Dictionary<string, bool> ChangeValues(int line, string[] keys)
{
Dictionary<string, bool> values = new Dictionary<string, bool>();
for (int i = 0; i < line; i++)
{
for (int j = 0, bit = 1; j < keys.Length; j++, bit <<= 1)
{
values[keys[j]] = (i & bit) != 0;
}
// do something with values here
}
return values;
}
Of course, in that case the values of the original dictionary are of no use, so there's no need to pass it in, so I've left it out of the parameter list for this version of the method.
If in fact you want to return a new dictionary but still need the old one for some reason (e.g. you want to do something with it, like copying values or something, which you failed to mention in your question), then you can combine the two examples above to suit your needs.
Do you mean like this:
static Dictionary<string, bool> ChangeValues(int line, Dictionary<string, bool> values)
{
switch (line)
{
case 0:
values["A"] = false;
values["B"] = false;
values["C"] = false;
break;
case 1:
values["A"] = false;
values["B"] = false;
values["C"] = true;
break;
case 2:
values["A"] = false;
values["B"] = true;
values["C"] = false;
break;
}
return values;
}
Note: You can also have void return type (as in static void ChangeValues) and omit the return values; statement since you always return the same instance anyway, but that depends on whether you want a "fluent syntax" or not.
After comments, try this:
static Dictionary<string, bool> ChangeValues(int line, Dictionary<string, bool> values)
{
var binary = Convert.ToString(line, 2);
var key = 'A';
foreach (var c in binary)
{
values[key.ToString()] = c == '1';
key++;
}
return values;
}
The comment about void is the same as before.
I have a class Cluster.cs defined as:
public class Cluster
{
protected int _clusterID = -1;
private static int _clusterCount = 0;
protected int _attributeCount;
// _clusterObjects contains EvoObjects in this cluster.
protected List<EvoObject> _clusterObjects = new List<EvoObject>();
/** _nkA[_i] is the total occurrences of the attribute _i in this cluster*/
protected Int32[] _nkA;
// For each attribute, record their values as KeyValuePair.
protected Dictionary<Int32, UtilCS.KeyCountMap<Int32>> _attributeValues = new Dictionary<Int32, UtilCS.KeyCountMap<Int32>>();
public Cluster(int _clusterID, int _attributeCount)
{
this._clusterID = _clusterID;
this._attributeCount = _attributeCount;
_nkA = new Int32[_attributeCount];
}
// Initialize _attributeValues
IEnumerable<Int32> _range = Enumerable.Range(0, _attributeCount).GetEnumerator(_i => {_attributeValues[_i] = new UtilCS.KeyCountMap<Int32>()});
}
while initializing _attributeValues, I got error as:
"No overloaded method for GetEnumerator takes 1 argument"
whereas I've only 1 argument to initialize i.e. _attributeValues which is actually a dictionary that's why have to enumerate at it.
Also if I declare _attributeCount static, I'm unable to use it in constructor and if I declar it non-static, I'm unable to use it Range method of Enumberable.
How will I initialize _attributeValues then?
How to declare _attributeCount static or non-static?
It looks like your trying to initialize the Dictionary by using a variable (_range) that is set at object creation. This should be moved into the constructor. It appears you are attempting to create three new attributes with keys 0,1,2 and values of new UtilCS.KeyCountMap().
If this is correct, then I would suggest using this as your constructor.
public Cluster(int _clusterID, int _attributeCount)
{
this._clusterID = _clusterID;
this._attributeCount = _attributeCount;
_nkA = new Int32[_attributeCount];
for (var i = 0; i < 3; i++)
{
_attributeValues.Add(i, new UtilCS.KeyCountMap<int>());
}
}
However, since you are sending in _attributeCount I would say you could use that instead of 3.
public Cluster(int _clusterID, int _attributeCount)
{
this._clusterID = _clusterID;
this._attributeCount = _attributeCount;
_nkA = new Int32[_attributeCount];
for (var i = 0; i < _attributeCount; i++)
{
_attributeValues.Add(i, new UtilCS.KeyCountMap<int>());
}
}
Enumerable.Range(0, _attributeCount).ToList().ForEach(x => _attributeValues.Add(x, new UtilCS.KeyCountMap<Int32>()));
I have the following foreach loop in my program:
Dictionary<string, int[]> summaryDate_clipsEpisodesImps = new Dictionary<string, int[]>();
Dictionary<string, int[]> summaryPartner_clipsEpisodesImps = new Dictionary<string, int[]>();
foreach (DataRow row1 in dt10.Rows)
{
int[] numbers = new int[3];
numbers[0] = 0;
numbers[1] = 0;
numbers[2] = 0;
if (!dictionary1.ContainsKey(row1["value1"].ToString().Trim()))
{
dictionary1.Add(row1["value1"].ToString().Trim(), numbers);
}
if (!dictionary2.ContainsKey(row1["value2"].ToString().Trim()))
{
dictionary2.Add(row1["value2"].ToString().Trim(), numbers);
}
if (row1["yes_or_no"].ToString().Trim() == "yes")
{
dictionary1[row1["value1"].ToString().Trim()][0] = dictionary1[row1["value1"].ToString().Trim()][0] + Convert.ToInt32(row1["a_number"]);
dictionary2[row1["value2"].ToString().Trim()][0] = dictionary2[row1["value2"].ToString().Trim()][0] + Convert.ToInt32(row1["a_number"]);
}
}
Essentially, I am looping through a datatable and creating a dictionary of string/int arrays based on values that I find in each record. Then I'm trying to increment the first value in the array based on the presence of another field in the record.
My problem occurs in the if statement when I check for the yes_or_no value. When the second line incrementing dictionary2 is present in this statement, the value in dictionary 1 is incremented by the same value. I have no idea why this is the case.
Please let me know if this isn't entirely clear. Thanks in advance for the help.
This is because the values in both dictionary entries point to the same instance of numbers. This means any change to one will affect the other.
To put a new instance in each dictionary you could do something similar to:
...
if (!dictionary1.ContainsKey(row1["value1"].ToString().Trim()))
{
dictionary1.Add(row1["value1"].ToString().Trim(), GetNumbersArray());
}
if (!dictionary2.ContainsKey(row1["value2"].ToString().Trim()))
{
dictionary2.Add(row1["value2"].ToString().Trim(), GetNumbersArray());
}
...
private int[] GetNumbersArray()
{
int[] numbers = new int[3];
numbers[0] = 0;
numbers[1] = 0;
numbers[2] = 0;
return numbers;
}
You're adding a pointer to the array to each dictionary. Both dictionaries look at the same array, so when you modify the array through dictionary2, dictionary1 sees the changes.