Reputation: 4364
Suppose you have a list defined as:
List<string> list1 = new List<string>{"Cat","Dog","Bird","Badger"};
Now, suppose you wanted to write a generic function that could take that list and change the length of it. So if you're subtracting the length to make the list smaller, it would truncate the items within the list, or if the length is longer, it would copy the contents of the List and then add new additional indices to it.
A bigger length parameter would result in:
List<string> list1 = new List<string>{"Cat","Dog","Bird","Badger","","","","",""};
while a smaller length would result in:
List<string> list1 = new List<string>{"Cat","Dog"};
Assuming that no deep copying needed to be done, how could a function like this be written?
Upvotes: 0
Views: 1112
Reputation: 5156
You can use AddRange
and RemoveRange
, which is better than looping with Add
and/or RemoveAt
:
public static void PaddedResize<T>(
List<T> list,
int size,
T padding = default(T)
) {
// Compute difference between actual size and desired size
var deltaSize = list.Count - size;
if (deltaSize < 0) {
// If the list is smaller than target size, fill with `padding`
list.AddRange(Enumerable.Repeat(padding, -deltaSize));
} else {
// If the list is larger than target size, remove end of list
list.RemoveRange(size, deltaSize);
}
}
This works for immutable, referentially transparent, or struct types, but for the garden variety class, it will pad the list with the same element over and over, which might be non-ideal. To fix that, take a factory function that creates the padding instead:
public static void PaddedResize<T>(
List<T> list,
int size,
Func<T> paddingFactory // Changed parameter to a factory function
) {
// Compute difference between actual size and desired size
var deltaSize = list.Count - size;
if (deltaSize < 0) {
// If the list is smaller than target size, fill with the result of calling `paddingFactory` for each new item
list.AddRange(Enumerable.Repeat(0, -deltaSize).Select(_ => paddingFactory()));
} else {
// If the list is larger than target size, remove end of list
list.RemoveRange(size, deltaSize);
}
}
Upvotes: 4
Reputation: 457
You may want to create some ListUtils
class and write static generic functions there. In case you want a new list containing needed items
static class Listutils
{
public static List<T> Shrink<T>(List<T> src, Predicate<T> predicate)
{
if (src == null || src.Count == 0)
return null;
List<T> newList = new List<T>();
foreach(T item in src)
{
if (predicate(item))
newList.Add(item);
}
return newList;
}
}
........somewhere in your program
List<string> list = new List<string>{"Cat","Dog","Bird","Badger","Snake"};
// select only Cat, Dog and Bird
List<string> shrinked = ListUtils.Shrink(list, (name) => delegate
{
return (name == "Cat" || name == "Dog" || name == "Bird");
});
Upvotes: -2