Resizing List<T> - c#

I want to resize my List<T>. ie. change the count of the List with respect to some conditions. Right now, Iam doing it using an Array like so :-
private MyModel[] viewPages = GetPagesFromAPI().ToArray();
if (viewPages.Count % 6 == 0)
{
Array.Resize(ref newViewPages, viewPages.Length / 6);
}
else
{
Array.Resize(ref newViewPages, viewPages.Length / 6 + 1);
}
But, I believe this is not a proper way to do it, since this would be heavy on my application and may cause memory issues. Is there a way I can do it using something likeList<MyModel> viewPageList?
Any help is appreciated.

I want to resize my List<T>
You have misunderstood the purpose of a List<T>. By definition, a list is an auto re-sizing collection, there is no need to manually resize it. As you add elements, it will check it's internal array backing storage and increase it's size when it needs to (the current implementation detail will double it's backing store).
This is how List<T>.Add is implemented:
// Adds the given object to the end of this list. The size of the list is
// increased by one. If required, the capacity of the list is doubled
// before adding the new element.
public void Add(T item)
{
if (_size == _items.Length) EnsureCapacity(_size + 1);
_items[_size++] = item;
_version++;
}
EnsureCapacity will make sure the backing array has sufficient storage.

Related

Remove last item of Stack [duplicate]

Is there a built in way to limit the depth of a System.Collection.Generics.Stack? So that if you are at max capacity, pushing a new element would remove the bottom of the stack?
I know I can do it by converting to an array and rebuilding the stack, but I figured there's probably a method on it already.
EDIT: I wrote an extension method:
public static void Trim<T> (this Stack<T> stack, int trimCount)
{
if (stack.Count <= trimCount)
return;
stack = new
Stack<T>
(
stack
.ToArray()
.Take(trimCount)
);
}
So, it returns a new stack upon trimming, but isn't immutability the functional way =)
The reason for this is that I'm storing undo steps for an app in a stack, and I only want to store a finite amount of steps.
What you are looking for is called a dropout stack. AFAIK, the BCL does not contain one, although they are trivial to implement. Typically Undo and Redo functionality relies on such data structures.
They are basically an array, and when you push onto the stack the 'top' of the stack moves around the array. Eventually the top will wrap back to the beginning when the stack is full and replace the 'bottom' of the stack.
Google didn't provide much info on it. This is the best i could find:
(Warning PDF)
http://courses.cs.vt.edu/~cs2704/spring04/projects/DropOutStack.pdf
Here's some boiler plate code, to get you started. I'll let you fill in the rest (sanity checking, count, indexer, etc.)
class DropOutStack<T>
{
private T[] items;
private int top = 0;
public DropOutStack(int capacity)
{
items = new T[capacity];
}
public void Push(T item)
{
items[top] = item;
top = (top + 1) % items.Length;
}
public T Pop()
{
top = (items.Length + top - 1) % items.Length;
return items[top];
}
}
You're actually looking at something similar to circular list implementation. There's a LimitedQueue implementation done by PIEBALDconsult at CodeProject. It's similar to your requirement. You just need to wrap Stack instead of Queue as done by the author. Plus the author also implemented indexer, which is handy if you need to access anything else other than the top stack (to show undo list maybe).
EDIT: The author's implementation also raise an event when the last(first, depends on whether it's a queue or stack) is being removed, so that you can know when something is being thrown away.
I can't see a way. You can inherit from Stack<T>, but there doesn't appear to be anything useful to override.
The easy (if a bit tedious) way would be to wrap the Stack<T> in your own, say, LimitedStack<T>. Then implement the methods you want and pass through to an internal Stack<T>, while including your limiting logic in the Push method and wherever else you need it.
It's a pain to write all those pass-through members, especially if you're implementing all the same interfaces as Stack<T>...but on the other hand, you only have to do it once and then it's done.
I believe you're looking for a (possibly-modified) dequeue - the data structure that allows access from either end.
the solution provided By Greg Dean => dropout stack is very good, but I think the main question, is about removing the bottom of the stack when the stack overflowed
But the provided solution just replace the last item of the stack once the stack was filled, so you do not get a real history,
But to get a real history, you need to shift the list once the list reaches your specific capacity, but this is an expansive operation,
So I think the best solution for this is a linked list
This is my solution to the problem
public class HistoryStack<T>
{
private LinkedList<T> items = new LinkedList<T>();
public List<T> Items => items.ToList();
public int Capacity { get;}
public HistoryStack(int capacity)
{
Capacity = capacity;
}
public void Push(T item)
{
// full
if (items.Count == Capacity)
{
// we should remove first, because some times, if we exceeded the size of the internal array
// the system will allocate new array.
items.RemoveFirst();
items.AddLast(item);
}
else
{
items.AddLast(new LinkedListNode<T>(item));
}
}
public T Pop()
{
if (items.Count == 0)
{
return default;
}
var ls = items.Last;
items.RemoveLast();
return ls == null ? default : ls.Value;
}
}
Test it
var hs = new HistoryStack<int>(5);
hs.Push(1);
hs.Push(2);
hs.Push(3);
hs.Push(4);
hs.Push(5);
hs.Push(6);
hs.Push(7);
hs.Push(8);
var ls = hs.Items;
Console.WriteLine(String.Join(",", ls));
Console.WriteLine(hs.Pop());
Console.WriteLine(hs.Pop());
hs.Push(9);
Console.WriteLine(hs.Pop());
Console.WriteLine(hs.Pop());
Console.WriteLine(hs.Pop());
Console.WriteLine(hs.Pop());
Console.WriteLine(hs.Pop()); // empty
Console.WriteLine(hs.Pop()); // empty
The Result
4,5,6,7,8
8
7
9
6
5
4
0
0

Store string data using an array (C#)

A task that I can't seem to solve, even after hours and hours of trying.
Basically, I have a phonebook that takes input from the user: name and number (both string type), which becomes a Contact.
I'm supposed to store the Contact in an Array, and the user shall both be able to add and also delete data (Contact) from the array, via the methods Create and Delete.
I made an own Repository class to handle the data (Contact also has an own little class), but I used List to store the data, so I could simply use Add and Remove, so my code looks like this:
public class Repository
{
List<Contact> storagelist;
public Repository() {
storagelist = new List<Contact>();
}
public void Create(Contact item) //Adds the item to the list
{
storagelist.Add(item);
}
public bool Delete(Contact item) //Removes the item
{
if (!storagelist.Contains(item))
return false;
storagelist.Remove(item);
return true;
}
}
What I am looking for, is how do exactly this, have these 2 features of adding and removing a Contact, but store the data in an Array instead.
Since arrays (to my knowledge) has to have a fixed, pre-defined size I have no idea how it could be used in exactly the same way as the List. The array size shall always be the same as the amount of Contacts that are stored, but how can this be done when an array's size is fixed??
So, how to create an array, that always has the same size as the amount of Contacts that are stored, and how to Add and Remove to/from this array?
Help is very much appreciated!
EDIT: Thanks for all responses! Every answer was helpful in the process (Omar and person66 in particular!).
I solved the Removal by "moving" the entire array after the delete-element, to 1 index lower, and finally resizing the array to be smaller. Like so:
int deleteIndex = Array.IndexOf(storagelist, item);
for (int index = deleteIndex + 1; index < storagelist.Length; index++)
{
storagelist[index - 1] = storagelist[index];
}
Array.Resize(ref storagelist, storagelist.Length - 1);
You are right in that array sizes are fixed. You can, however, use Array.Resize() to create a new array of the specified size with all the current array data. So for adding you would resize to 1 larger and add the new contact at the end. For removing you will have to use a loop to shift all the elements in the array past the one being removed back one spot, then resize it to be 1 smaller.
EDIT: A simpler option for removing would be to use Array.Copy():
Array.Copy(a, deleteIndex + 1, a, deleteIndex, a.Length - (deleteIndex + 1));
Array.Resize(ref a, a.Length - 1);
A list is a much better solution to this problem, I don't know why you would ever want to use an array for this.
A List just ends up using an array for it's storage anyway. The way a list works is it is initializes an array with a certain amount of storage then if it's capacity is exceeded it recreates an array with a larger size and copies the elements back. You could try this approach, except you'd just be recreating what a list does.
The other option is just declare an arbitrarily large array of 100,000 elements or so. A number which you know will not be exceeded.
For size you can write your own function which keeps track of the number of contacts in the array.
You can use a generic list. Under the hood the List class uses an array for storage but does so in a fashion that allows it to grow effeciently.
Take a look at this link for more details, it can be helpfull.
var contacts = new[]
{
new { Name = "Foo", Phone = "9999999999" },
new { Name = "Bar", Phone = "0000000000" }
};
You can create an array of anonymous object and then use linq to delete objects from array.
You can create a new object and insert into anonymous object variable.

How to truncate an array in place in C#

I mean is it really possible? MSDN says that arrays are fixed-size and the only way to resize is "copy-to-new-place". But maybe it is possible with unsafe/some magic with internal CLR structures, they all are written in C++ where we have a full memory control and can call realloc and so on.
I have no code provided for this question, because I don't even know if it can exist.
I'm not talking about Array.Resize methods and so on, because they obviosly do not have needed behaviour.
Assume that we have a standard x86 process with 2GB ram, and I have 1.9GB filled by single array. Then I want to release half of it. So I want to write something like:
MagicClass.ResizeArray(ref arr, n)
And do not get OutOfMemoryException. Array.Resize will try to allocate another gigabyte of RAM and will fail with 1.9+1 > 2GB OutOfMemory.
You can try Array.Resize():
int[] myArray = new int[] { 1, 2, 3, 4 };
int myNewSize = 1;
Array.Resize(ref myArray, myNewSize);
// Test: 1
Console.Write(myArray.Length);
realloc will attempt to do the inplace resize - but it reserves the right to copy the whole thing elsewhere and return a pointer that's completely different.
Pretty much the same outward behaviour is exposed by .NET's List<T> class - which you should be using anyway if you find yourself changing array sizes often. It hides the actual array reference from you so that the change is propagated throughout all of the references to the same list. As you remove items from the end, only the length of the list changes while the inner array stays the same - avoiding the copying.
It doesn't release the memory (you can always do that explicitly with Capacity = XXX, but that makes a new copy of the array), but then again, unless you're working with large arrays, neither does realloc - and if you're working with large arrays, yada, yada - we've been there :)
realloc doesn't really make sense in the kind of memory model .NET has anyway - the heap is continously collected and compacted over time. So if you're trying to use it to avoid the copies when just trimming an array, while also keeping memory usage low... don't bother. At the next heap compaction, the whole memory above your array is going to be moved to fill in the blanks. Even if it were possible to do the realloc, the only benefit you have over simply copying the array is that you would keep your array in the old-living heap - and that isn't necessarily what you want anyway.
Neither array type in BCL supports what you want. That being said - you can implement your own type that would support what you need. It can be backed by standard array, but would implement own Length and indexer properties, that would 'hide' portion of array from you.
public class MyTruncatableArray<T>
{
private T[] _array;
private int _length;
public MyTruncatableArray(int size)
{
_array = new T[size];
_length = size;
}
public T this[int index]
{
get
{
CheckIndex(index, _length);
return _array[index];
}
set
{
CheckIndex(index, _length);
_array[index] = value;
}
}
public int Length
{
get { return _length; }
set
{
CheckIndex(value);
_length = value;
}
}
private void CheckIndex(int index)
{
this.CheckIndex(index, _array.Length);
}
private void CheckIndex(int index, int maxValue)
{
if (index < 0 || index > maxValue)
{
throw new ArgumentException("New array length must be positive and lower or equal to original size");
}
}
}
It really depend what exactly do need. (E.g. do you need to truncate just so that you can easier use it from your code. Or is perf/GC/memory consumption a concern? If the latter is the case - did you perform any measurements that proves standard Array.Resize method unusable for your case?)

Sugar coated arrays (dynamically resizable and set any element at random)

I want my cake and to eat it.
I like the way Lists in C# dynamically expand when you go beyond the initial capacity of the array. However this is not enough. I want to be able to do something like this:
int[] n = new int[]; // Note how I'm NOT defining how big the array is.
n[5] = 9
Yes, there'll be some sacrifice in speed, because behind the scenes, .NET would need to check to see if the default capacity has been exceeded. If it has, then it could expand the array by 5x or so.
Unfortunately with Lists, you're not really meant to set an arbitrary element, and although it is possible if you do this, it still isn't possible to set say, the fifth element straight away without initially setting the size of the List, let alone have it expand dynamically when trying.
For any solution, I'd like to be able to keep the simple square bracket syntax (rather than using a relatively verbose-looking method call), and have it relatively fast (preferably almost as fast as standard arrays) when it's not expanding the array.
Note that I don't necessarily advocate inheriting List, but if you really want this:
public class MyList<T> : List<T>
{
public T this[int i]
{
get {
while (i >= this.Count) this.Add(default(T));
return base[i];
}
set {
while (i >= this.Count) this.Add(default(T));
base[i] = value;
}
}
}
I'll add that if you expect most of the values of your "array" to remain empty over the life of your program, you'll get much greater efficiency by using a Dictionary<int, T>, especially as the size of the collection grows large.
A simple solution to the problem is to inherit from Dictionary<TKey, TValue> and just use the value generic:
public class MyCoolType<T> : Dictionary<int, T> { }
Then you would be able to use it like:
MyCoolType<int> n = new MyCoolType<int>();
n[5] = 9;
And a note on performance.
For insertions, this is much faster than a list since it does not require you to resize or insert elements at arbitrary positions in an array. List<T> uses an array as a backing field and when you resize it, it is expensive. (Edit: Lists have a default size and its not always that you are resizing it, but when you do, its expensive)
For look-ups, this is very nearly O(1) (source), so comparable to an Array look-up. Lists are O(n), which get progressively slower as you increase the number of contained elements.
Sparsely packing is much more memory efficient than using a List with dense packing as it doesn't require you to use empty items just to reach a specific index.
Other Notes:
In the other solutions, try inserting an item at index 570442959 for example, you'll get an OutOfMemoryException thrown (under 32 bit, but even 64-bit has problems). With this solution you can use any conceivable index that the int type supports, up to int.MaxValue.
Lists don't allow negative indexes, this will.
MyCoolType.Count is the equivalent of the array Length property here.
Here are the results of my performance test:
Inserting 1 million elements into MyList: 29.4294424 seconds
Inserting 1 million elements into CoolType: 0.127499 seconds
Looking up 1 million random elements MyList: 1.6330562 seconds
Looking up 1 million random elements CoolType: 1.304348 seconds
Full source to tests here: http://pastebin.com/kEdLgFaw
Note, to run these tests I had to set to X64 build, debug, and had to add the following to the app.config file:
<runtime>
<gcAllowVeryLargeObjects enabled="true" />
</runtime>
Here is your pi
static public List<int> AddToList(int index,int value, List<int> input)
{
if (index >= input.Count)
{
int[] temparray = new int[index - input.Count + 1];
input.AddRange(temparray);
}
return (input[index] = value);
}
You can define an extension method on List:
public static class ExtensionMethods {
public static void Set<T>(this List<T> list, int index, T element) {
if (index < list.Count) {
list[index] = element;
} else {
for (int i = list.Count; i < index; i++) {
list.Add(default(T));
}
list.Add(element);
}
}
}
and call list.Set(12, 1024) if you want the 12th element to be 1024.

how does object of List<string> add the supplied string

Somebody please shed some light on how Add method is implemented for
(how Add method is implemented for List in c#)
listobject.Add();
where List<User> listobject= new List<User>() is the declaration for the object.
I know that using List we can perform many operations on a fly and that too with type safety, but what I wonder is how id add method implemented so that it takes care of all that at run time.
Hope it doesnot copy the object and make adjustment on each add but I will keep my fingers crossed and wait for your reply :)
Using Reflector you can see exactly how its implemented.
public void Add(T item)
{
if (this._size == this._items.Length)
{
this.EnsureCapacity(this._size + 1);
}
this._items[this._size++] = item;
this._version++;
}
Following 'EnsureCapacity' ...
private void EnsureCapacity(int min)
{
if (this._items.Length < min)
{
int num = (this._items.Length == 0) ? 4 : (this._items.Length * 2);
if (num < min)
{
num = min;
}
this.Capacity = num;
}
}
And finally the setter for 'Capacity'
public int Capacity
{
get
{
return this._items.Length;
}
set
{
if (value != this._items.Length)
{
if (value < this._size)
{
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value, ExceptionResource.ArgumentOutOfRange_SmallCapacity);
}
if (value > 0)
{
T[] destinationArray = new T[value];
if (this._size > 0)
{
Array.Copy(this._items, 0, destinationArray, 0, this._size);
}
this._items = destinationArray;
}
else
{
this._items = List<T>._emptyArray;
}
}
}
}
Internally the List<T> holds the items in an array. The actual implementation (List<string>) is created at compile-time runtime (thanks #Jason for the correction), so internally there will be a string array that holds the items.
For reference types the list will hold a reference to the same object instance that you added. This is true for strings as well. However, note that the string class is immutable, so any time you modify a string, it actually results in a new instance.
string a = "a";
List<string> list = new List<string>();
list.Add(a); // now the item in the list and a refer to the same string instance
a = "b"; // a is now a completely new instance, the list
// is still referring the old one
No it will work on the string reference, otherwise there wouldn't be much point in using it if it always cloned you're objects.
You can actually check this sort of thing within Visual Studio by using the memory screens, it's possible to compare the address of the added item, and the original and you'll see that they point to the same memory location.
As Frederik notes, List uses an array internally. It creates the array with an initial size and as more items are added, if the array is filled to capacity, it is copied into a larger array. That is why if you know ahead of time that a List will contain many strings, it can help to specify its initial capacity in the constructor.
When you remove items from the list, or insert in the middle, it must shift all the elements in the internal array so a List is not particularly optimized for adding/removing many items. You may be better off using a LinkedList which is much more efficient at add/remove operations but gives up the ability to efficiently access elements in the list by position.
Different collections have different implementations that are best suited for certain scenarios. For a good example of how various collections are implemented, I suggest checking out PowerCollections library that was released by Wintellect. Many of the collections are no longer relevant in .NET 3.5/4.0 but they provide some great insight on how to go about implementing collections.
For a List, the Add method will be of generic type T, in this case a string. The content of the list will be a reference to the original variable, so if you modify the string in the list it will modify the original and vice versa.

Categories

Resources