How Add values to var myDictionary = new Dictionary<int, Values>() - c#

I created a public struct Values that has public string value1and public string value2.
public struct Values
{
public string header;
public string type;
}
My dictionary:
var myDictionary = new Dictionary<int, Values>();
Question: How do I add two values for each key?
while (true)
{
for (int i = 0; i < end i++)
{
myDictionary.Add(i, value1 , value2);
}
}

If you want to generate dictionary, you can try using Linq:
var myDictionary = Enumerable
.Range(0, end)
.Select(i => new {
key = i,
value = new Values() {
header = HeaderFromIndex(i), //TODO: implement this
type = TypeFromIndex(i) //TODO: implement this
}})
.ToDictionary(item => item.key, item => item.value);
In case you want to add items into existing dictionary:
for (int i = 0; i < end; ++i)
myDictionary.Add(i, new Values() {
header = HeaderFromIndex(i), //TODO: implement this
type = TypeFromIndex(i) //TODO: implement this
});
Please notice, that in any case dictionary holds pairs: {key, value}; so if you want to have two items as values for the corresponding key, you have to organize the values into a class new Values() {header = ..., type = ...} in your case

If I get the question correctly, you have to initialize a Values object and than add this one to your dictionary. Like this:
while (true) {
for (int i = 0; i < end i++) {
Values tmp_values;
tmp_values.header = "blabla";
tmp_values.type = "blabla type";
myDictionary.Add(i, tmp_values);
}
}

Related

Dictionary to return a character list with their indices

I've been tasked with taking a string and returning a dictionary that has a map of characters to a list of their indices in a given string. The output should show which characters occur where in the given string.
This code passes the test:
public class CharacterIndexDictionary
{
public static Dictionary<string, List<int>> ConcordanceForString(string input)
{
var result = new Dictionary<string, List<int>>();
for (var index = 0; index < input.Length; index++)
{
// Get the character positioned at the current index.
// We could just use input[index] everywhere, but
// this is a little easier to read.
string currentCharacter = input[index].ToString();
// If the dictionary doesn't already have an entry
// for the current character, add one.
if (!result.ContainsKey(currentCharacter))
{
result.Add(currentCharacter, new List<int>());
}
// Add the current index to the list for
// the current character.
result[currentCharacter].Add(index);
}
return result;
}
}
If I wanted to index characters I'd use a Dictionary<char, List<int>> instead of using a string as the key, but this uses string because the test requires it.
This code block is like your code and in a way that you can understand
public Dictionary<string, List<int>> ConcordanceForString(string s)
{
Dictionary<string, List<int>> newDictionary = new Dictionary<string, List<int>>();
List<char> charList = new List<char>();
foreach (var item in s)
{
if (!charList.Any(x => x == item))
{
charList.Add(item);
List<int> itemInds = new List<int>();
for (int i = 0; i< s.Length; i++)
{
if (s[i] == item)
{
itemInds.Add(i);
}
}
newDictionary.Add(item.ToString(), itemInds);
}
}
return newDictionary;
}

C# Dictionary, Sum of value from one key?

I have a Dictionary and use it as a save game.
public Dictionary<string, inventoryvars> inventar = new Dictionary<string, inventoryvars>();
public bool Additem(string Planetname, int WWlvl, int AKlvl, int BaGebLvl, int UwLvl, int Exlvl)
{
inventoryvars ip = new inventoryvars();
if (!inventar.ContainsKey(Planetname))
{
ip.name = Name;
ip.WWlvl = WWlvl;
ip.AKlvl = AKlvl;
ip.UwLvl = UwLvl;
ip.Exlvl = Exlvl;
inventar.Add(name, ip);
return true;
}
else
{
inventar[name].anzahl += 1;
return true;
}
return true;
}
Now i need to get the sum of all Exlvl. Lets say, there are 5 items, every item has Exlvl with a different value.
Sorry for my english, it's not my first language.
The Solution is: inventar.Sum(x => x.Value.BaGebLvl);
Thanks everybody!
You can use the Values property to get all instances of inventoryvars and use LINQ Sum() against them
var result = inventar.Values.Sum(x => x.Exlvl)
(OR)
var result = inventar.Sum(x => x.Value.Exlvl)
you can make a funtion that return the sum of keys in your collection?
public int sumOfKeysValues(public Dictionary input)
{ int result = 0;
foreach(var item in input)
{
var key = (inventoryvars)item.key;
result += key.Exlvl;
}
}

C# Variable not getting all values outside for loop

I have two values in the dictionary but when I try to get the two values outside the loop I am only getting one value. The locationdesc variable value are being overwritten. Is there a better way to create unique variables to handle this issues
There are two keys location-1 and location-2. I am trying to figure out how to get both the values outside the loop. Am I doing it wrong?
string locationDesc = "";
string locationAddress = "";
int count = dictionary.Count(D => D.Key.StartsWith("location-"));
for (int i = 1; i <= count; i++)
{
if (dictionary.ContainsKey("location-"+i))
{
string locationData = dictionary["location-"+i];
string[] locationDataRow = locationData.Split(':');
locationDesc = locationDataRow[0];
locationAddress = locationDataRow[1];
}
}
// Only getting location-2 value outside this loop since locationDesc is not unique.
Debug.WriteLine("Location Desc from dictionary is : " + locationDesc);
Debug.WriteLine("Location Add from dictionary is : " + locationAddress);
What I would like to get here is get both the values like locationDesc1 and locationDesc2 instead of locationDesc
What I am looking for is to create locationDesc and locationAddress unique so I can access both the values outside the for loop.
More Explanation as I was not very clear:
I have a dynamic table that will be created in the front end. Every time a location is created I create a cookie. For e.g. location-1, location-2 ...location-n with the location description and location values as values in the cookie. I am trying to access these values in the backend by creating a dictionary so I can assign all the values to unique variable which will make it easier for me to pass these values to a api call. I think I am over complicating a simple issue and might be doing it wrong.
My api call will be something like this:
<field="" path="" value=locationDesc1>
<field="" path="" value=locationDesc2>
The problem with your loop is that you are relying on the position of the entry in the dictionary matching the index within your loop. Your first line of code pretty much has it though:
int count = dictionary.Count(D => D.Key.StartsWith("location-"));
What this tells me is that you are looking for all entries in your dictionary where the key starts with "location-". So why not do that directly:
var values = dictionary.Where(d => d.Key.StartsWith("location-"));
And to do the extraction/string splitting at the same time:
var values = dictionary
.Where(d => d.Key.StartsWith("location-"))
.Select(d => d.Item.Split(':')
.Select(s => new
{
LocationDesc = s[0],
LocationAddress = s[1]
});
This will give you an IEnumerable of LocationDesc/LocationAddress pairs which you can loop over:
foreach(var pair in values)
{
Debug.WriteLine(pair.LocationDesc);
Debug.WriteLine(pair.LocationAddress);
}
Try this:
int count = dictionary.Count(D => D.Key.StartsWith("location-"));
Dictionary<string, string> values = new Dictionary<string, string>();
for (int i = 1; i <= count; i++)
{
if (dictionary.ContainsKey("location-"+i))
{
string locationData = dictionary["location-"+i];
string[] locationDataRow = locationData.Split(':');
values.Add(locationDataRow[0],locationDataRow[1]);
}
}
foreach (var item in values)
{
Debug.WriteLine(item.Key + " : " + item.Value);
}
As you are dealing with multiple values, you should go with a container where you can store all the values.
if you are dealing with only two unique values then use below code.
int count = dictionary.Count(D => D.Key.StartsWith("location-"));
string[] locationDesc = new string[2];
string[] locationAddress = new string[2];
for (int i = 1; i <= count; i++)
{
if (dictionary.ContainsKey("location-"+i))
{
string locationData = dictionary["location-"+i];
string[] locationDataRow = locationData.Split(':');
locationDesc[i-1] = locationDataRow[0];
locationAddress[i-1] = locationDataRow[1];
}
}
for (int i = 0; i <= locationDesc.Length-1; i++)
{
Debug.WriteLine("Location Desc from dictionary is : " + locationDesc[i]);
Debug.WriteLine("Location Add from dictionary is : " + locationAddress[i]);
}
if number of unique values is not fixed then go with ArrayList
int count = dictionary.Count(D => D.Key.StartsWith("location-"));
ArrayList locationDesc = new ArrayList();
ArrayList locationAddress = new ArrayList();
for (int i = 1; i <= count; i++)
{
if (dictionary.ContainsKey("location-"+i))
{
string locationData = dictionary["location-"+i];
string[] locationDataRow = locationData.Split(':');
locationDesc.Add(locationDataRow[0]);
locationAddress.Add(locationDataRow[1]);
}
}
for (int i = 0; i < locationDesc.Count; i++)
{
Debug.WriteLine("Location Desc from dictionary is : " + locationDesc[i]);
Debug.WriteLine("Location Add from dictionary is : " + locationAddress[i]);
}
Simple One. If you only want to show result using Debug.WriteLine, then go with below code
int count = dictionary.Count(D => D.Key.StartsWith("location-"));
for (int i = 1; i <= count; i++)
{
if (dictionary.ContainsKey("location-"+i))
{
string locationData = dictionary["location-"+i];
string[] locationDataRow = locationData.Split(':');
Debug.WriteLine("Location Desc from dictionary is : " + locationDataRow[0]);
Debug.WriteLine("Location Add from dictionary is : " + locationDataRow[1]);
}
}
Not able to prepare Code in Visual Studio at the moment therefore there may be some syntax errors.
It is hard to judge what you are event trying to do. I would not just be dumping objects you already have into other objects for fun. If you are just trying to expose values in a loop for use with another function, you can just use LINQ to iterate over the dictionary. If you want a specific value just add a where LINQ expression. LINQ should be in any .NET framework after 3.5 I believe.
public static void ApiMock(string s)
{
Console.WriteLine($"I worked on {s}!");
}
static void Main(string[] args)
{
var d = new Dictionary<int, string> {
{ 1, "location-1" },
{ 2, "location-2" },
{ 3, "location-3" }
};
d.ToList().ForEach(x => ApiMock(x.Value));
//I just want the second one
d.Where(x => x.Value.Contains("-2")).ToList().ForEach(x => ApiMock(x.Value));
//Do you want a concatenated string
var holder = string.Empty;
d.ToList().ForEach(x => holder += x.Value + ", ");
holder = holder.Substring(0, holder.Length - 2);
Console.WriteLine(holder);
}

Is there a "DataTable" with "named row" in C#?

I need a data structure with both named column and row. For example:
magic_data_table:
col_foo col_bar
row_foo 1 3
row_bar 2 4
I need to be able to access elements like magic_data_table["row_foo", "col_bar"] (which will give me 3)
I also need to be able to add new columns like:
magic_data_table.Columns.Add("col_new");
magic_data_table["row_foo", "col_new"] = 5;
AFAIK, DataTable only has named column...
EDIT:
I don't need to change the name of a column or a row. However, I may need to insert new rows into the middle of the table.
While you could use a Dictionary<string, Dictionary<string, T>> to do what you want, that wouldn't be particularly efficient in terms of memory, and would have the potential for the inner dictionaries to get out of sync. If you create your own data structure though that is a facade for lists, using dictionaries to map column names to indexes, then it's simple enough:
public class MyDataStructure<T>//TODO come up with better name
{
private Dictionary<string, int> columns;
private Dictionary<string, int> rows;
private List<List<T>> data;
public MyDataStructure(
IEnumerable<string> rows,
IEnumerable<string> columns)
{
this.columns = columns.Select((name, index) => new { name, index })
.ToDictionary(x => x.name, x => x.index);
this.rows = rows.Select((name, index) => new { name, index })
.ToDictionary(x => x.name, x => x.index);
initData();
}
private void initData()
{
data = new List<List<T>>(rows.Count);
for (int i = 0; i < rows.Count; i++)
{
data.Add(new List<T>(columns.Count));
for (int j = 0; j < columns.Count; j++)
{
data[i].Add(default(T));
}
}
}
public T this[string row, string column]
{
//TODO error checking for invalid row/column values
get
{
return data[rows[row]][columns[column]];
}
set
{
data[rows[row]][columns[column]] = value;
}
}
public void AddColumn(string column)
{
columns.Add(column, columns.Count);
for (int i = 0; i < data.Count; i++)
{
data[i].Add(default(T));
}
}
public void AddRow(string row)
{
rows.Add(row, rows.Count);
var list = new List<T>(columns.Count);
data.Add(list);
for (int i = 0; i < columns.Count; i++)
{
list.Add(default(T));
}
}
public bool RenameRow(string oldRow, string newRow)
{
if (rows.ContainsKey(oldRow) && !rows.ContainsKey(newRow))
{
this.Add(newRow, rows[oldRow]);
this.Remove(oldRow);
return true;
}
return false;
}
}
Note that if you were willing to fix the rows/columns upon construction then you'd be able to use a T[,] as the backing for the data, which would both make the class dramatically simpler to implement, and further reduce the memory overhead, although that doesn't appear to work for your use cases.
Add a column for the name - "name" in the following:
DataTable table = ...
DataColumn nameCol = table.Columns["name"];
var index = table.Rows.Cast<DataRow>()
.ToDictionary(row => (string)row[nameCol]);
... // then when you need the values:
string rowName = ..., colName = ...
var val = index[rowName][colName];
You may find that the Tuple (.net 4.0 and above) class suits your needs. It won't work strictly like a table but will give you a lot of flexibility.
You can use the List<> generic to store it and LINQ to query your data.
List<Tuple<string, string, int>> magicTable = new List<Tuple<string, string, int>>();
magicTable.AddRange(new Tuple<string, string, int>[] {
Tuple.Create("row_foo", "col_foo", 1),
Tuple.Create("row_foo", "col_bar", 2),
Tuple.Create("row_bar", "col_foo", 3),
Tuple.Create("row_bar", "col_bar", 4)});
magicTable.Add(Tuple.Create("row_foo", "col_new", 5));
int value = magicTable.Single(tuple => (tuple.Item1 == "row_foo" && tuple.Item2 == "col_new")).Item3;
It is going to be quite resource intensive due to the duplication of row/column names but you do get a lot of flexibility for small datasets.
Microsoft's Tuple documenation (3-tuple): http://msdn.microsoft.com/en-us/library/dd387150.aspx

An integer array as a key for Dictionary

I wish to have the dictionary which uses an array of integers as keys, and if the integer array has the same value (even different object instance), they will be treated as the same key. How should I do it?
The following code does not work as b is different object instances.
int[] a = new int[] { 1, 2, 3 };
int[] b = new int[] { 1, 2, 3 };
Dictionary<int[], string> dic = new Dictionary<int[], string>();
dic.Add(a, "haha");
string output = dic[b];
You can create an IEqualityComparer to define how the dictionary should compare items. If the ordering of items is relevant, then something like this should work:
public class MyEqualityComparer : IEqualityComparer<int[]>
{
public bool Equals(int[] x, int[] y)
{
if (x.Length != y.Length)
{
return false;
}
for (int i = 0; i < x.Length; i++)
{
if (x[i] != y[i])
{
return false;
}
}
return true;
}
public int GetHashCode(int[] obj)
{
int result = 17;
for (int i = 0; i < obj.Length; i++)
{
unchecked
{
result = result * 23 + obj[i];
}
}
return result;
}
}
Then pass it in as you create the dictionary:
Dictionary<int[], string> dic
= new Dictionary<int[], string>(new MyEqualityComparer());
Note: calculation of hash code obtained here:
What is the best algorithm for an overridden System.Object.GetHashCode?
Maybe you should consider using a Tuple
var myDictionary = new Dictionary<Tuple<int,int>, string>();
myDictionary.Add(new Tuple<int,int>(3, 3), "haha1");
myDictionary.Add(new Tuple<int,int>(5, 5), "haha2");
According to MSDN , Tuple objects Equals method will use the values of the two Tuple objects
The easiest way if you don't care about actual hashing may just be to convert the array into a string. Adding a space to avoid numbers joining.
dic.Add(String.Join(" ",a), "haha");

Categories

Resources