If I have a list of 100 integers, how would I assign the values at index 20 to 50 to a different set of values in a list of length 31 without the use of loops? Coming from python this is very easy to do without looping but am unsure if it is possible to do in c#.
-
3When you say "without loops", are you allowed to use something that uses loops, like LINQ?Caius Jard– Caius Jard2020-12-30 19:11:01 +00:00Commented Dec 30, 2020 at 19:11
-
5It's logically impossible to do this without loops and without hard-coding the indexes. Please define what you actually wantCamilo Terevinto– Camilo Terevinto2020-12-30 19:15:14 +00:00Commented Dec 30, 2020 at 19:15
-
How would you do it in Python? We could show you something functionally equivalent.Nechemia Hoffmann– Nechemia Hoffmann2020-12-30 19:54:37 +00:00Commented Dec 30, 2020 at 19:54
3 Answers
Using LINQ, which is "without using loops in my code", you could:
hundredInts.Take(19).Concat(thirtyoneInts).Concat(hundredInts.Skip(50));
(and if you want it back as a list or array etc, the relevant ToXXX call on the end of it)
Or perhaps:
hundredInts.Select((n, i) => (i < 20 || i > 50) ? n : thirtyOneInts[i-20])
Or built in stuff:
hundredInts.RemoveRange(20, 31).InsertRange(20, thirtyOneInts);
4 Comments
There's no trivial way to do so with Lists. However, this is easily done with arrays using Array.Copy:
var destIndex = 20;
Array.Copy(sourceArray, 0, destArray, destIndex, sourceArray.Length)
Comments
Well, if you can use loops under the hood, you can create an extension method, like
public static class MyExtensions{
public static void SetRange<T>(this List<T> source, IEnumerable<T> newValues, int startIndex){
var newValuesList = newValues.ToArray();
int numberOfElements = Math.Min(source.Count - startIndex, newValues.Count());
for(int i = 0; i < numberOfElements; i++){
source[i + startIndex] = newValuesList[i];
}
}
}
And use like the following:
var list = Enumerable.Range(0, 100).ToList();
var list2 = Enumerable.Range(1000, 31).ToList();
list.SetRange(list2, 20);
This will replace the values in list, starting at index 20, to the values of list2. You can also modify the extension method to add another parameter to estipulate the number of elements that you will take from list2, like the following:
public static void SetRange<T>(this List<T> source, IEnumerable<T> newValues, int startIndex, int numberOfElements){
var newValuesList = newValues.ToArray();
numberOfElements = Math.Min(numberOfElements, source.Count - startIndex);
numberOfElements = Math.Min(numberOfElements, newValues.Count());
for(int i = 0; i < numberOfElements; i++){
source[i + startIndex] = newValuesList[i];
}
}
You should probably also add a validation if startIndex and numberOfElements are greater than or equal to 0.