List with empty index - c#

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.

Related

What if I never create new object but keep adding the old object into the List by just updating it's value

In a for loop, instead of declaring a new object and add it to my List, I just update the value of the old object and every time keep adding this old object to my List, why after a few loops all List elements become the same
foreach (vg_ts_VesselCashflow_CashFlow_Entity item in cashflow)
{
var result = new VslMonthlyCashflow_Record();
result.CapitalCost = item.CapitalCost;
result.CharterRevenue = item.CharterRevenue;
result.Date = item.Period;
result.DryDock = item.DryDock;
resultList.Add(result);
}
if (resultList != null)
return resultList;
//Compared with this:
var result = new VslMonthlyCashflow_Record();
foreach (vg_ts_VesselCashflow_CashFlow_Entity item in cashflow)
{
result.CapitalCost = item.CapitalCost;
result.CharterRevenue = item.CharterRevenue;
result.Date = item.Period;
result.DryDock = item.DryDock;
resultList.Add(result);
}
I expect my resultList to be updated but if I keep using the old object, when it loops 123 times, all elements in the List will be the same.
List#Add doesn't copy the object or anything like that, it just keeps a reference to the object you passed to it. In the second snippet, you keep adding the same object to the list multiple times. Each modification you perform on the object is visible through all the references pointing to it, including the local result variable and all the elements of the list.

How to set object value instead of reference?

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";

C# Dynamic Array/ index

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

nested hashset of lists?

I'm working on one of the project Euler problems, and I wanted to take the approach of creating a list of values, and adding the list to a Hashset, this way I could evaluate in constant time if the list already exists in the hashset, with the end goal to count the number of lists in the hashset for my end result.
The problem I'm having is when I create a list in this manner.
HashSet<List<int>> finalList = new HashSet<List<int>>();
List<int> candidate = new List<int>();
candidate.Add(5);
finalList.Add(candidate);
if (finalList.Contains(candidate) == false) finalList.Add(candidate);
candidate.Clear();
//try next value
Obviously the finalList[0] item is cleared when I clear the candidate and is not giving me the desired result. Is it possible to have a hashset of lists(of integers) like this? How would I ensure a new list is instantiated each time and added as a new item to the hashset, perhaps say in a for loop testing many values and possible list combinations?
Why don't you use a value which is unique for each list as a key or identifier? You could create a HashSet for your keys which will unlock your lists.
You can use a Dictionary instead. The only thing is you have to test to see if the Dictionary already has the list. This is easy to do, by creating a simple class that supports this need.
class TheSimpleListManager
{
private Dictionary<String, List<Int32>> Lists = new Dictionary<String, List<Int32>>();
public void AddList(String key, List<Int32> list)
{
if(!Lists.ContainsKey(key))
{
Lists.Add(key, list);
}
else
{
// list already exists....
}
}
}
This is just a quick sample of an approach.
To fix your clear issue: Since its an object reference, you would have to create a new List and add it to the HashSet.
You can create the new List by passing the old one into its constructor.
HashSet<List<int>> finalList = new HashSet<List<int>>();
List<int> candidate = new List<int>();
candidate.Add(5);
var newList = new List<int>(candidate);
finalList.Add(newList);
if (finalList.Contains(newList) == false) //Not required for HashSet
finalList.Add(newList);
candidate.Clear();
NOTE: HashSet internally does a contains before adding items. In otherwords, here even if you execute finalList.Add(newList); n times, it would add newList only once. Therefore it is not necessary to do a contains check.

Way to fill List<> with elements

I have in my code
List<BookedReelsState> retVal = new List<BookedReelsState>(somesize);
Match later in the code if some condition works I need to fill this entire List with same value.
Of course I can do it via foreach loop and set values , Is there more elegant way to do so ?
I just to learn something new here .
retVal.AddRange(Enumerable.Repeat(value, somesize));
retVal.ForEach(b => b.changedProp = newValue);
Two things here.
Firstly List<T>(int capacity) does not create a List with capacity items in it already. It just reserves memory for them. So the list in the example above will have it's length equals to 0.
But if you have a list and want to set each element of it, you can do it like this:
retVal.ForEach( rv => rv = desiredValue );
Where desiredValue is the value you want to set for each element.
I also find it strange that you want to fill every single element of a list with the same value. If all elements are the same the list serves no purpose, but I guess that you might need to fill with some default value up front, and then change some of them later on.
If you have an IEnumerable then you can use List.AddRange.
Example:
var list = new List<BookedReelsState>(20);
var someEnumerable = new []
{
new BookedReelsState(1),
new BookedReelsState(2),
new BookedReelsState(2)
};
list.AddRange(someEnumerable);

Categories

Resources