I've asked that question in a different manner and noone answered me, now I'm asking this with an example, hope It's crystal clear what I'm trying to do.
List<object> l1 = new List<object>() {"string1", "string2"};
Dictionary<string, object> map = new Dictionary<string, object>();
map.Add("aKey", l1[l1.Count - 1]);
object obj = map["aKey"];
What to do with obj in order to change l1[1] value it currently points to?
obj = "newString"; will set obj to "newString" and leave l1[1] - that is "string2" unchanged, because object is a reference type. but I don't want that
Or at least get 1 and l1 out of it.
My whole design is such that I have a storage in the form of two List.
For example you call Engine.Save
Save will get last element from list 2 by default, though if it's given a key as argument it will get the coresponding element from one of the two lists. Than will decide the element's type and save it accordingly or log error message.
I can't easily explain that, nor can I post that much code.
In the dictionary, you could store a reference to the list and the index separately, using tuples:
// Set up the list.
var myList = new List<object>() {"string1", "string2"};
// Set up the dictionary.
var myDict = new Dictionary<string, Tuple<List<object>, int>>();
myDict.Add("myKey", new Tuple<List<object>, int>>(myList, myList.Count - 1));
// Update the list by using the dictionary.
var theTuple = myDict["myKey"];
var theList = theTuple.Item1;
var theIndex = theTuple.Item2;
theList[theIndex] = "newString";
Related
I am creating an array of string[] in my c# program to save location ("name","Position") of a bunch of elements. The problem is any time I had to introduce a new element I have to change the code at several places according to index of elements:
string[] list = new string[4];
list[0] = "[ELEMENT #1 NAME],[ELEMENT #1POSITION]";
list[1] = "[ELEMENT #2 NAME],[ELEMENT #2POSITION]";
list[2] = "[ELEMENT #3 NAME],[ELEMENT #3POSITION]";
list[3] = "[ELEMENT #4 NAME],[ELEMENT #4POSITION]";
What I am looking for is something like an dynamic array so that I do not have to change the index location every time I introduce/ remove an element from list.
You can use List<string> as a dynamic array, it supports IEnumerable<string> for enumerating, or you can call LINQ and ToArray().
For example:
var list = new List<string>();
list.Add("[ELEMENT #1 NAME],[ELEMENT #1POSITION]");
string array[] = list.ToArray();
However, I'd actually recommend a dictionary in this case and not a list, a dictionary will let you store key-value pairs.
For example:
var dict = new Dictionary<string,int>();
dict["Element #1 Name"] = #Element #1 Position#;
Note that I've no real idea what type the position is, could be an int, a string or even a Point, but you get the idea.
You then don't need to bother with indices but refer to everything by name:
var el1_pos = dict["Element #1 Name"];
var el999_pos = dict["Element #999 Name"];
You can use List<T> if you want a dynamically sized collection and don't bother with the index. And you should also create a type with two properties (Name and Position) and have a list of that type instead of storing them as string. It's easier to maintain, you don't have to parse the string every time you wanna get/set the Name or Position of a particular object.
Normally, you would just use a List<String> here. The Add method allows you to just add an element, no indexing required.
List<string> list = new List<string>();
list.Add("Test");
In your case, since you have "Name" and "Position" associated with each other, consider using a List<PositionedThing> (a custom class in other words) or a Dictionary<String, String> to store your mappings.
The class would look like:
public class PositionedThing
{
public String Name {get; set;}
public String Position {get; set;}
}
Try
List<string> list = new List<string>();
list.Add("[ELEMENT #1 NAME],[ELEMENT #1POSITION]")
Unless I've misunderstood your question that should be what you want
I need a container for multiple items that should have predetermined amount of objects that may or may not be null. Like
List<objects> with capacity of 4
List[0] = new Object();
List[1] = null;
List[2] = new Object();
List[3] = new Object();
I need to be able to set any index to null without getting problems when iterating through the list even if all or some are null.
This is because i need each object to have a specific place in the list and i also need each place/index to be able to be empty.
I guess lists are not the correct option, what alternatives are there?
You can use a list of Object (or any other type you want).
You can initialise it with a set number of nulls (or any other value):
List<Object> list = Enumerable.Repeat<Object>(null, 10).ToList();
And then modify only certain positions:
list[3] = "value1";
list[5] = 1;
list[7] = null;
Iterating over this list will work ok.
How do I make a generated Object name? For example:
ObjectEx "name" = new ObjectEx();
Edit:
The object will be named by a user input.
The code will be:
Console.Write("Input new user's name: ");
string newUsersName = Console.ReadLine();
(Create ObjectEx)
Edit2:
I have a Dictionary for ObjectEx(Person) which handles all ObjectExs.
Person is the real class name, sorry about making the example object ObjectEx.
public static List<Person> persons = new List<Person>();
Objects don't have names - variables do, and they're always determined at compile-time.
If you want a map from string to object, just use a Dictionary<string, ObjectEx> - then come with random strings using Random. (There are plenty of examples of generating random strings on Stack Overflow.)
If you just want a collection of objects and you were using "random name" as a way of expressing that, use List<ObjectEx> - you don't need a name at all in that case.
If you need something else, please be more specific.
You can use array and store object in to that.
ObjectEx []arrObjectEx = new ObjectEx[10];
arrObjectEx[0] = new ObjectEx();
I would use list<T> (generic list) instead of array if the number of random elements are unknown.
List<ObjectEx> lstObjectEx = new List<ObjectEx>();
lstObjectEx.Add(new ObjectEx());
If randomly generated object need to be accessed uniquely then you can use dictionary. e.g
Dictionary<int, ObjectEx> dicObjectEx = new Dictionary<int, ObjectEx>();
dicObjectEx.Add(someUniqueNumber, new ObjectEx());
That is not possible but how about using a Dictionary. You can use a string value Add and Get hold of an Object you stored.
// somewhere near the start in your code initialize the dictionary
var dict = new Dictionary<string, Person>();
// later on you can dynamically add an Object to the Dictionary
// newUsersName is the so called Index
string newUsersName = Console.ReadLine();
dict.Add(newUsersName, new Person());
// if you need to get hold of that object again use the Index
// myObj is a Person type
var myObj = dict[newUsersName];
// assume Person has an Age property
myObj.Age = 20;
// show all Persons now in the dictionary
foreach(var username in dict.Keys)
{
Console.WriteLine(username);
var pers = dict[username];
Console.WriteLine("{0} is {1} years old", username, pers.Age );
}
You could use a dictionary to store objects, where the Key is the object name
I am currently working on a project which creates a dictionary with an int index of the instance and a complex type as the value. Since this is a huge school project I do not want to post a ton of code as I have a logic problem rather than a "I need code". I'll try to be as clear as I can and if there is something I need to explain better please let me know.
First off. I have a dictionary in my server:
private Dictionary<int,List<complexType>> dictName = new Dictionary<int,List<complexType>>
Every time a client starts up it registers with the dictionary (i create a blank complex type to instantiate it then i load the dictionary):
List<complexType> temp = null;
dictName.Add(id,temp)
Then when the time comes that I want to add to the list for a particular instance I do this:
complexType myItem = new complexType();
dictName[id].Add(myItem);
When I run this code I get an error when a second client tries to run:
"An unhandled exception of type
'System.Reflection.TargetInvocationException' occurred in
mscorlib.dll. Additional information: Exception has been thrown by the
target of an invocation.
Now this happens when the second user hits:
dictName.Add(id,temp) from the first part.
If i change the instantiation of temp to List<complexType> temp = new List<complexType>();
then it passes that spot but I get the same error again when it updates the clients.
I am currently using this way of passing data with int and string (dictionary)
and they work fine but when I added in a List of a complex type in the dictionary I got the above error.
If anyone has any suggestions I would greatly appreciate it. I'm hoping it has something to do with my initial load of a blank list. If there is anything else you need to know please Ask Thanks!
You are making a dictionary of lists. So you were trying to add to a list that was null and that is what gave you the first exception.
Second, I've never seen the "new private Dictionary" is this a cut and paste typo?
This works:
Dictionary<int, List<string>> dictName = new Dictionary<int, List<string>>();
dictName.Add(0, new List<string>());
dictName[0].Add("First");
dictName.Add(1, new List<string>());
dictName[1].Add("Second");
The fact that you have list of a complex type and I have list of strings shouldn't matter.
Looks like you should initialize the dictionary entry as:
dictName.Add(id, new List<complexType>());
You can also try using the generic Lookup type, which is basically exactly what you need - key to a list of values.
var lookupName = new Lookup<int, complexType>();
lookup.Add(id, new complexType()); // Creates key 'id' and adds new ct.
lookup.Add(id, new complexType()); // Adds new ct to existing key 'id'
lookup.Add(651, null); // Creates key 651 and adds null
So you can just use the add method to add complex type instances to an id key without even thinking of whether the key exists or not.
lookup[id]
Will return you an IEnumerable of the complex types linked to the given id.
Example:
var lu = new Lookup<int, string>();
lu.Add(7, "Seven");
lu.Add(7, "SEVEN");
lu.Add(4, "Four");
lu.Add(7, "7");
lu.Add(4, "FOUR");
lu.Add(4, "FOUR");
Console.WriteLine(string.Join(", ", lu[7])); // "Seven, SEVEN, 7"
Console.WriteLine(string.Join(", ", lu[4])); // "Four, FOUR, FOUR"
foreach (var grp in lu)
{
int id = grp.Key;
foreach (var str in grp)
{
...
}
}
Try this way:
Dictionary<int, List<string>> dictName = new Dictionary<int, List<string>>();
dictName.Add(0, null);
dictName[0] = new List<string>();
dictName[0].Add("Hello");
Here is my problem:
I have two dictionaries with identical structures:
Dictionary<string, List<Object>> Existing
Dictionary<string, List<Object>> New
Basically what I need to do is to first find any List<Object> that is in New but not in Existing based on the key and then find any Object in each List<Object> contained in New that does not exist in its corresponding List<Object> in Existing or is changed based on a number of properties in Object and, of course, the dictionary key.
I'm currently doing this by looping and checking each object individually, but I thought there must be a better way to do this using LINQ.
Hopefully that is clear, but let me know if you need further info.
Thanks.
As for new entries in the dictionary and new objects within an entry's List<object>:
List<object>[] addedLists = New.Keys.Except(Existing.Keys)
.Select(key => New[key])
.ToArray();
object[] addedObjects = Existing.Keys.Intersect(New.Keys)
.SelectMany(key => New[key].Except(Existing[key])
.ToArray();
But the last requirement is a bit unclear. How would you define a changed object? Which objects should be compared for change? Comparing any object with any other object would potentially be defined as different, so there must be some similarities on which to base a comparison (e.g. the objects with the same value in their ID property).
EDIT: As you clarified in your comment how object identity is defined, here's how to find all changed objects (assuming the dictionary's value is a list of Foo that has a properties Name and Type that identify the object and property Value that may change:
var differences = Existing.Keys.Intersect(New.Keys).SelectMany(key =>
from existingObj in Existing[key]
join newObj in New[key] on new { existingObj.Name, existingObj.Type } equals
new { newObj.Name, newObj.Type }
where existingObj.Value != newObj.Value
select new { Key = key, Existing = existingObj, New = newObj });
This will produce a sequence of objects each containing the key of the dictionary the difference was found in, the existing object and the new object. Identical objects will not be included in the results.
Dictionary<string, int> New = new Dictionary<string, int>();
Dictionary<string, int> Existing = new Dictionary<string, int>();
New.Add("A", 100);
New.Add("B", 200);
New.Add("Y", 300);
New.Add("X", 400);
Existing.Add("A", 1);
Existing.Add("B", 2);
Existing.Add("C", 3);
Existing.Add("D", 4);
Existing.Add("E", 5);
Existing.Add("F", 6);
Existing.Add("G", 7);
Existing.Add("H", 8);
var newStuff = New.Where(n => !Existing.ContainsKey(n.Key)).ToList();
var updatedStuff = Existing.Where(e => New.ContainsKey(e.Key) && e.Value != New.Single(n => n.Key == e.Key).Value);
newStuff.Dump();
updatedStuff.Dump();
//updated and new
newStuff.AddRange(updatedStuff);
newStuff.Dump();
Done in Linqpad.