Way to fill List<> with elements - c#

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

Related

List elements are dependant from each other

For some reason, elements in my list(Maps = new List<CollisionTiles>[]) are dependant from each other. This list contains information about collision tiles in my game. The problem is, when I set list elements in Map list to Maps[Something], Maps list is changing too, whenever I do anything with Map after assignation.
if (mapClass.Maps[3].Count != 0)
{
mapClass.ClearMap(); // CollisionTiles.Clear(); BackGroundTiles.Clear();
mapClass.CollisionTiles = mapClass.Maps[3];
mapClass.BackgroudTiles = mapClass.SpriteMaps[3];
}
if (mapClass.Maps[3].Count == 0)
{
mapClass.GenerateCustomMap(64, 10, 8, 3, false);
}
Really difficult to say from the code you've posted but based on your description you might be copying a "reference" to a collection when you intended to copy the collection itself.
For example, let's say to have a list called a and you try to make a another list called b like this:
var a = new List<string>();
var b = a;
What the above code is actually doing is making a and b a "reference" to the same list.
In other words, if you then did something like this:
b.Add("item");
Now both of the "lists" called a and b will have the same items in them. That's because they are not actually different lists, they are the same list with two "pointers".
There's a couple of different ways you can correctly copy of a list in C#. One way is to pass the list into the constructor like this:
var a = new List<string>();
a.Add("item");
var b = new List<string>(a);
This will give you two separate lists with that both have an item in them. However, now when you modify either of those lists they won't change together.
A popular (more modern) alternative approach for the code above can be done by using System.Linq namespace.
var a = new List<string>();
a.Add("item");
var b = a.ToList();
I hope that helps.
You are setting mapClass.CollisionTiles to reference to the original List.
Therefore, any modifications to the mapClass.CollisionTiles changes the original List as well. The same goes for BackgroundTiles.
To correct this, create new List objects when assigning them to the mapClass:
if (mapClass.Maps[3].Count != 0)
{
mapClass.ClearMap(); // CollisionTiles.Clear(); BackGroundTiles.Clear();
mapClass.CollisionTiles = new List<CollisionTiles>(mapClass.Maps[3]);
mapClass.BackgroudTiles = new List<BackgroudTiles>(mapClass.SpriteMaps[3]);
}
else // this is the only other option from the above if
{
mapClass.GenerateCustomMap(64, 10, 8, 3, false);
}
Please note, I have left the misspelling of BackgroudTiles, please correct as necessary.

C# how to "delete" first value of array, reorder array and set last value back at 0?

So I've got a Datapoint[] = new Datapoint[50] that I'm filling. As soon as the Datapoint array is full, how can I "delete" Datapoint[0] and set Datapoint[1] to Datapoint[0], Datapoint[2] to Datapoint[1]... etc. and make Datapoint[49] free again / to value 0/0?
I didn't had any success yet figuring it out since I don't wanna use a loop.
Thanks for help!
One option to consider would be to create a completely new array and assign it to your existing variable.
The code would look something like:
existingVariableName = existingVariableName
.Skip(1)
.Concat(new Datapoint[] { new Datapoint() })
.ToArray();
Skip(1) means to skip over the existing first element. Concat is used to add a new element at the end. ToArray materialises the LINQ query into the new resulting array.

C# use LINQ to query custom list and return new subset list

I have a list of a custom type called Holdings. I am trying to query the list based on one property of the Holdings object to return a new list of Holdings. The LINQ query below does work correctly but I would like to replace var unitHld with List unitHld but can't get the code to work.
var unitHld = from hld in _holdingList
where hld.FundCode == lookThroList[i].FundCode
select new Holding() { Currency = hld.Currency,
FundCode = lookThroList[i].FundCode,
IdSedol = hld.IdSedol,
Nominal = hld.Nominal * unitWgt,
Price = hld.Price };
This new list is then slightly altered before being added back to the original list (I know the logic sounds strange but please accept this is how it has to be done). However because unitHld is var the line below does not work.
_holdingList.Add(unitHld);
The following call only adds a single item (where the item must be the same type as the list's elements):
_holdingList.Add(unitHld);
But you want to add a range of items, so do it like this:
_holdingList.AddRange(unitHld);
where unitHld is IEnumerable<T> and T is the type of the list's elements.
(This answer assumes that holdingList is of type List<T>, and that T is in fact Holding for your example.)
See List.AddRange() for details.
C# is statically typed.
var is not a type, all it does is a shortcut for in your case typing IEnumerable<Holding>.
If you want the result to be List<Holding> then all you need to do is wrap your query in brackets and put .ToList() at the end.
However, to append this to another list, you don't need to do that. Simply call .AddRange on the other list.
Alternatively, you can use Concat
var bothLists = aList.Concat(anotherList);
I would like to replace var unitHld with List unitHld but can't get the code to work.
You need to call ToList() on the result of the query:
var unitHld = from hld in _holdingList
where hld.FundCode == lookThroList[i].FundCode
select new Holding() { Currency = hld.Currency,
FundCode = lookThroList[i].FundCode,
IdSedol = hld.IdSedol,
Nominal = hld.Nominal * unitWgt,
Price = hld.Price };
List<Holding> unitHldList = unitHld.ToList();
This new list is then slightly altered before being added back to the original list
Once the data is in unitHldList, you can alter it as needed.
the line below does not work. _holdingList.Add(unitHld);
When you add the content of a collection to a List<T>, use AddRange method instead of Add:
_holdingList.AddRange(unitHldList);
Try this:
_holdingList.AddRange(unitHld);

How to keep values from a List<T> in a model after clearing the list?

I have a List that receives ids. It is instantiated outside the foreach statement.
List<int> indices = new List<int>();
foreach (var m in docsRelacionadosModel)
{
//.. do stuff
modelTemp.indices = indices;
//..here I do more stuff and some time it goes to the next iteration and I need to keep the value in indices to get more values.
//although in a condition
if(isOk) {
//I save the value of this list to a model
model.indices = modelTemp.indices;
//And I need to clear the list to get new values
indices.Clear(); <--- This will clear the values saved in model.indices
}
}
As it has values passed by reference, how can I keep the values in model.indices?
You need to make a copy of the list and save that copy to model.indecies. While there are a number of ways of copying the list the LINQ ToList extension method is probably the most convenient:
model.indices = modelTemp.indices.ToList();
Another option is to just use the List constructor:
model.indices = new List<int>(modelTemp.indices);
Just create a copy of the list:
model.indices = new List<int>(modelTemp.indices);
As per this S/O question, the easiest way may be to call ToList on your list:
model.indices = modelTemp.indices.ToList();
You could also instantiate as a new list, passing your list as a constructor parameter.

How could I determine if an array contains a value at a particular index?

I have an array with values at meaningful indices. How can I tell if a particular there is a value at a particular element?
Array.Exists() is the closest I've found, but it looks overcomplicated for what I want, so I'm curious to know if it's really the best way.
UPDATE
OK, so I have an array of objects:
ImageGroup[] Images;
And the index of the elements corresponds to a feature of that item. In this case, the index refers to a value within the filename of the original image. When I come across a filename, I want to check if an element exists at the corresponding index and create one if not.
So I want to know if Images[someInt] exists.
Updated
With the last update this looks more like a dictionary (unless you're going in numerical order and not where "1,2,5" may have been populated, but 3,4 are absent and need to be created). If this is something where index could potentially skip, I would recommend a dictionary:
Dictionary<Int32,Image> images = new Dictionary<Int32, Image>();
// populated previously
Int32 needle = GetIndexOfImage(newImage);
if (!images.ContainsKey(needle))
images.Add(needle, newImage);
Then, once you're done populating, you can then re-reference the item by index in the following fashion:
images[specificIndex]
Once more, you can retrieve all the elements stored using the following as well:
images.Values
Some resources:
Dictionary
Dictionary.ContainsKey
First response:
if (a[index] == interesting) ....
After the Edit(s):
int index = GetIndexFromFilename(filename);
// if (Images[index] != null && Images[index] == interesting) ....
if (Images[index] == null)
Images[index] = CreateImage(filename);
But you should probably just use a Dictionary<string, Image> and use filename as the Key.
It sounds like what you're looking for is the functionality of a dictionary. It would be extremely helpful if you posted how you're populating your array, and how you want to be able to index it. From what I can gather, this is how I would implement...
Dictionary<SomeEnum, ImageGroup> images = new Dictionary<SomeEnum, ImageGroup>();
foreach(SomeEnum enumValue in Enum.GetValues(typeof(SomeEnum)))
{
ImageGroup group = BuildImageGroup();
images.Add(enumValue, group);
}
then you can do:
...
if(images.ContainsKey(SomeEnum.SomeValue))
return images[SomeEnum.SomeValue];
else
return DoSomethingFancy();
If you have multiple image groups for a single enum value (collisions), then you can use a collection of ImageGroups in the dictionary, like this:
Dictionary<SomeEnum, ImageGroup[]>

Categories

Resources