I know there is no reference to "struct" variable in C#, but this is the case where it would come handy
Dictionary<int, int> d = new Dictionary<int, int>();
d.Add(1, 1);
++d[1];
++d[1];
how can I perform 2 operations (increment in this case) on the same element without using operator[] twice (to prevent double lookup)?
You can create a mutable reference type that wraps another value, in this case an immutable value type, allowing the value of the wrapper to be mutated:
public class Wrapper<T>
{
public T Value { get; set; }
}
This lets you write:
Dictionary<int, Wrapper<int>> d = new Dictionary<int, Wrapper<int>>();
d.Add(1, new Wrapper<int>(){Value = 1});
var wrapper = d[1];
wrapper.Value++;
wrapper.Value++;
Related
I'm trying to a build a simple app and the main point is I must use dictionary. I will have data like this in my dictionary:
(key,number,number,number,number)
So below is my code which implements my data.
Dictionary<string,int,int,int,int> states = new Dictionary<string,int,int,int,int>();
I have looked at many sources for how to solve it, but I couldn't find it.
I get an error that it must have a two arguments.
Can you give me a solution to make a dictionary can hold more than 2 arguments?
You can create a class to hold the 4 numbers like this:
public class MyData
{
public int Number1 {get;set;}
public int Number2 {get;set;}
public int Number3 {get;set;}
public int Number4 {get;set;}
}
And use it as the dictionary value type like this:
Dictionary<string,MyData> states = new Dictionary<string,MyDate>();
Here is a code example that adds an item to the dictionary:
states.Add("my_key", new MyData { Number1 = 1, Number2 = 2, Number3 = 3, Number4 = 4});
To access data for a specific key, you can use:
MyData data = states["my_key"];
int number1 = data.Number1;
//...
To iterate over all data, you can use a simple foreach like this:
foreach(var kvp in states)
{
var key = kvp.Key;
var data = kvp.Value;
var number1 = data.Number1;
//...
}
Another alternative for MyData would be the Tuple class. But having your own type is probably better because you can have your own names for the 4 number properties.
If the names of the last four integers does not matter, you can use
Dictionary<string, List<int>>
By this way, you can get your int list with your string key, and then enumerate the list.
OR you can go with any array type such as
Dictionary<string, int[]>
In project I often use "containers" that store different number of values that have various types.
For example for 2 and 3 values:
class Nodes2<K, V> {
public K Key { get; set; }
public V Value { get; set; }
}
class Nodes3<T1, T2, T3> {
public T1 Value1 { get; set; }
public T2 Value2 { get; set; }
public T3 Value3 { get; set; }
}
Then I use them in collections:
List<Nodes3<int, string, double>> descriptions = new List<Nodes3<int, string, double>>();
That well suites for simple cases, when there is no neŃessity for create individual class for every such case.
So, the question is: are there in .NET built-in classes that can hold values like in my case?
Yes, there are. For key-values you have Dictionary<K,V>.
For node holders, you have Tuple (All the way up to 8 elements). Although a bit cumbersome (IMO), you can use them an access your items via Item1, Item2, etc.
And you use them like this:
var tuple = Tuple.Create("Hello", 0);
var hello = tuple.Item1;
var zero = tuple.Item2;
Yes, Tuple, with it's implementations with extra generic type parameters. (Tuple<T>, Tuple<T1, T2>, etc.). Tuple is available from .NET 4.
From MSDN:
var tuple1 = Tuple.Create(12);
Console.WriteLine(tuple1.Item1)
And:
var tuple2 = Tuple.Create("New York", 32.68);
Console.WriteLine("{0}: {1}", tuple2.Item1, tuple2.Item2);
And so on.
There's already a class made for this Tuple.
List<Tuple<int, string, double>> lists = new List<Tuple<int, string, double>>();
lists.Add(Tuple.Create<int, string, double>(5, "string", 10d));
I am very new to .NET, used to working in PHP. I need to iterate via foreach through a dictionary of objects. My setup is an MVC4 app.
The Model looks like this:
public class TestModels
{
Dictionary<int, dynamic> sp = new Dictionary<int, dynamic>
{
{1, new {name="abc", age="1"}},
{2, new {name="def", age="2"}}
}
}
Controller:
public class TestController : Controller
{
Models.TestModels obj = new Models.TestModels();
}
How do I loop through the obj object and retrieve the values of the dictionary and print them in the view?
One way is to loop through the keys of the dictionary, which I recommend:
foreach(int key in sp.Keys)
dynamic value = sp[key];
Another way, is to loop through the dictionary as a sequence of pairs:
foreach(KeyValuePair<int, dynamic> pair in sp)
{
int key = pair.Key;
dynamic value = pair.Value;
}
I recommend the first approach, because you can have more control over the order of items retrieved if you decorate the Keys property with proper LINQ statements, e.g., sp.Keys.OrderBy(x => x) helps you retrieve the items in ascending order of the key. Note that Dictionary uses a hash table data structure internally, therefore if you use the second method the order of items is not easily predictable.
Update (01 Dec 2016): replaced vars with actual types to make the answer more clear.
It depends on what you are after in the Dictionary
Models.TestModels obj = new Models.TestModels();
foreach (var keyValuPair in obj.sp)
{
// KeyValuePair<int, dynamic>
}
foreach (var key in obj.sp.Keys)
{
// Int
}
foreach (var value in obj.sp.Values)
{
// dynamic
}
You can do it like this.
Models.TestModels obj = new Models.TestModels();
foreach (var item in obj.sp)
{
Console.Write(item.Key);
Console.Write(item.Value.name);
Console.Write(item.Value.age);
}
The problem you most likely have right now is that the collection is private. If you add public to the beginning of this line
Dictionary<int, dynamic> sp = new Dictionary<int, dynamic>
You should be able to access it from the function inside your controller.
Edit: Adding functional example of the full TestModels implementation.
Your TestModels class should look something like this.
public class TestModels
{
public Dictionary<int, dynamic> sp = new Dictionary<int, dynamic>();
public TestModels()
{
sp.Add(0, new {name="Test One", age=5});
sp.Add(1, new {name="Test Two", age=7});
}
}
You probably want to read up on the dynamic keyword as well.
public class TestModels
{
public Dictionary<int, dynamic> sp = new Dictionary<int, dynamic>();
public TestModels()
{
sp.Add(0, new {name="Test One", age=5});
sp.Add(1, new {name="Test Two", age=7});
}
}
I have two dictionaries. When I change a value in dictionary 1, the same change appears in dictionary 2. How do I change a value only in dictionary 1, not in dictionary 2 as well?
List<Dictionary<string, string>> ld1 = new List<Dictionary<string, string>>();
Dictionary<string, string> d1 = new Dictionary<string,string>();
d1.Add("Text", "Value1");
d1.Add("Format", "Value2");
ld1.Add(d1);
List<Dictionary<string, string>> ld2 = new List<Dictionary<string, string>>(ld1);
// ld2 = ld1
ld1[0]["Text"] = "Eulav"; // should: change only in the first dictionary
// actually: changes in the second dictionary as well
Console.WriteLine(ld1[0]["Text"]);
Console.WriteLine(ld2[0]["Text"]);
Outputs
Eulav
Eulav
You only create a new list but the items in that list reference the same objects (dictionaries), so you need to create a copy of each item as well:
var ld2 = new List<Dictionary<string, string>>();
foreach (var dict in ld1)
{
ld2.Add(new Dictionary<string, string>(dict));
}
If you want to have two shallow copies of a particular Dictionary<TKey, TValue> then just use the constructor to create a copy
Dictionary<string, string> ld1 = ...;
Dictionary<string, string> ld2 = new Dictionary<string, string>(ld1);
Note: In this particular case it will be a deep copy since string is immutable and has no child data which needs to be deeply copied
The point to remember here is that though you are creating two instances (Two distinct memory allocations) of List, you are only creating "one" instance of Dictionary.
Thus, both the lists have the same memory pointer, pointing to the same dictionary. And it is obvious that the change in one will update the other too.
As suggested by others, here you need to create one more instance of Dictinary (A distinct memory allocation) and copy the values of the first one to it.
Dictionary<string, string> ld2 = new Dictionary<string, string>(ld1);
Doing this will store different instances in list and changes in one will not effect other.
user1158781 in order do it with non inmutable objects like strings, you will have to clone every element of the dictionary to a new one.
You can implement the IClonable interface. I leave a litle example:
class Program
{
static void Main(string[] args)
{
Dictionary<int, Person> dic1 = new Dictionary<int, Person>();
dic1.Add(0, new Person { Name = "user1158781" });
Dictionary<int, Person> dic2 = new Dictionary<int, Person>();
foreach (var item in dic1)
{
dic2.Add(item.Key, (Person)item.Value.Clone());
}
dic1[0].Name = "gz";
Console.WriteLine(dic1[0].Name);
Console.WriteLine(dic2[0].Name);
}
class Person : ICloneable
{
public string Name { get; set; }
public object Clone()
{
return new Person { Name = this.Name };
}
}
}
I am using below code :
var list = new Collection<ArrayList>
{
new ArrayList
{
1,
"Test1"
},
new ArrayList
{
2,
"Test2"
},
};
In the above code I want to avoid the ArrayList and use the Generics. Is it possible in the above code?
Edit:
Above I have used only two values in one arraylist object, I may have multiple items of int's and string's in it.
You can't mix types in a generic list (unless the generic type is object, but that equates to ArrayList and is just a perversion of generics).
But you can create a class that contains a string and int and use that as the generic parameter for a generic list.
public class MyClass
{
public MyString string { get; set; }
public MyInt int { get; set; }
}
var list = new Collection<MyClass>
{
new MyClass { MyInt = 1, MyString = "Test1" },
new MyClass { MyInt = 2, MyString = "Test2" }
}
Another alternative, if using .NET 4.0 is to use a Tuple, though I would rather have a strongly typed class.
(untested code):
var list = new Collection<Tuple<int,string>>
{
Tuple.Create(1, "Test1"),
Tuple.Create(2, "Test2")
}
No.
The whole point of generics is that you can't put an int and a string in the same collection.
Instead, you should create your own class with int and string properties, then create a generic collection of that class.
Not really, the fact that you have different types makes using a generic pointless.
You could use List<object> instead of ArrayList but there's really no point. Instead you could create a custom class to hold the 2 values and use that in a generic type.
John
Maybe you need Dictionary?
var list = new Dictionary<int, string>
{
{ 1, "Test1" },
{ 2, "Test2" }
};
var list = new List < Dictionary<int, string>> ();
then you can populate it was data as you need.
I'm not sure what you are actually trying to achieve, but it seems to me you are trying to mimic the behavior of a dictionary or map, that can map two different values to each other. These values could be of any type you want.
Something like this:
Dictionary<int, string> d = new Dictionary<int, string>();
d.Add(1, "Test1");
d.Add(2, "Test2");
and you can handle your data as simple as:
string t1 = d[1]; //will hold "Test1"
string t2 = d[2]; //will hold "Test2"
Do you want something like this?