ToSkip elements on C# circular list - c#

I've to create an extension method jump<T> that, taken an arbitrary sequence s, returns an infinite sequence whose elements are obtained visiting in a circular way s and skipping n elements. So, if step == 0, then all the sequence is returned (infinite times), if step == 1, let's take all the numbers in the interval [0-10] as an example, will return 0,2,4,6,8,10,1,3,5 ecc. If step==2 then the result will be 0,3,6,9,1,4,7,10.
Obviously this is only an example with an ordered list of int, i need to do so with a generic sequence of T elements.
How can i achieve that?
To test it, i created a nunit test as following:
[Test]
public void Jumping_validArg_IsOk()
{
var start = new[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
.Jumping(3)
.ToList()//remove this to make it work
.Take(4);
var expected = new[] {1, 5, 9, 2};
CollectionAssert.AreEquivalent(start, expected);
}
but it seems to never end and it throws a System.OutOfMemoryException.
The solution:
I modified a little what i selected as best answer to make it more general in this way:
public static IEnumerable<T> Jump<T>(this IEnumerable<T> sequence, int step)
{
var pos = 0;
var list = sequence.ToList();
while (true)
{
yield return list[pos];
pos = (pos + step + 1) % list.Count;
}
}
In this way it should work with all the IEnumerable. I added a comment on the test to show what to delete to make it work. I hope it's all correct.

You can implement this very easily with a yield return statement:
public static IEnumerable<T> Jump<T>(this IList<T> data, int step) {
int pos = 0;
while(true) {
yield return data[pos];
pos = (pos + step) % data.Count;
}
}

Related

How to implement a specialized overload of the List.RemoveAll method, with an index parameter in the predicate?

The List<T>.RemoveAll is a quite useful method, that allows to remove efficiently multiple items from a list. Unfortunately in some scenarios I needed some extra features that the method doesn't have, and some guarantees that the documentation doesn't provide. It also has a questionable behavior in case the match predicate fails, that causes me anxiety. So in this question I am asking for an implementation of the same method, in the form of an extension method, with these features and characteristics:
Instead of a Predicate<T> it accepts a Func<T, int, bool> delegate, where the int is the zero-based index of the T item.
It guarantees that the predicate will be invoked exactly once for each item, in a stricly ascending order.
In case the predicate returns true for some items and then fails for another item, the items that have been elected for removal are removed from the list before the propagation of the exception.
Here is the signature of the extension method that I am trying to implement:
public static int RemoveAll<T>(this List<T> list, Func<T, int, bool> predicate);
It returns the number of elements that were removed.
I attempted to implement it using as starting point the existing implementation, but it has some performance optimizations that make it quite complex, and injecting the desirable "exceptional" behavior is not obvious. I am interested for an implementation that is simple and reasonably efficient. Using LINQ in the implementation is not desirable, because it implies memory allocations that I would like to avoid.
Context: I should demonstrate the behavior of the built-in List<T>.RemoveAll method, and explain why I don't like it. In case the match predicate fails for an item in the middle of the list, the items that have already been elected for removal are either not removed, or they are replaced with duplicates of other elements. In all cases the list retains its original size. Here is a minimal demo:
List<int> list = new(Enumerable.Range(1, 15));
Console.WriteLine($"Before RemoveAll: [{String.Join(", ", list)}]");
try
{
list.RemoveAll(item =>
{
if (item == 10) throw new Exception();
bool removeIt = item % 2 == 1;
if (removeIt) Console.WriteLine($"Removing #{item}");
return removeIt;
});
}
catch { } // Ignore the error for demonstration purposes
finally
{
Console.WriteLine($"After RemoveAll: [{String.Join(", ", list)}]");
}
The list has 15 numbers, and the intention is to remove the odd numbers from the list. The predicate fails for the 10th number.
Output:
Before RemoveAll: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
Removing #1
Removing #3
Removing #5
Removing #7
Removing #9
After RemoveAll: [2, 4, 6, 8, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
Online demo.
As you can see the numbers 1 and 3 have been removed, the 5, 7 and 9 are still there, and the numbers 6 and 8 have been duplicated (there are two occurrences of each). On the contrary the output that I expected to see is:
After RemoveAll: [2, 4, 6, 8, 10, 11, 12, 13, 14, 15]
This would be a reasonable and predictable behavior I could count on. It keeps the levels of danger in a manageable level. I am not risking, for example, duplicating items in a virtual shopping cart, or printing twice some PDF documents from a selection. The existing behavior stretches a bit too much my comfort levels.
I have reported this behavior to Microsoft, and the feedback that I've got is that in case of failure the outcome is undefined. From their point of view there is no difference between the two above outputs (the actual and the expected). Both are equally corrupted, because both represent a state that is neither the original nor the final/correct state after a successful execution. So they don't think that there is any bug that needs to be fixed, and doing changes that could potentially affect negatively the performance of successful executions is not justified. They also believe that the existing behavior is not surprising or unexpected, so there is no reason to document it.
This solution is based on the idea to separate the selection of the items to be removed from the removal itself.
This has the following advantages:
If during the selection process, an exception occurs, the list will be left untouched
The removal process can only fail in catastrophic cases (OutOfMemoryException etc.)
But of course also some disadantages:
it requires extra memory to store the intermediate selection result
some optimizations might not be as effective
Because of the mentioned optimizations, I chose to base the selection result on ranges instead of individual indexes, so we can use List.RemoveRange which if more effective than individual RemoveAt calls (assumed that there are in fact ranges with more than one element).
public static List<(int start, int count)> GetIndexRanges<T>(this List<T> list,
Func<T, int, bool> predicate)
{
var result = new List<(int start, int count)>();
int start = -1;
for (var i = 0; i < list.Count; i++)
{
// see note 1 below
bool toBeRemoved = predicate(list[i], i);
if (toBeRemoved)
{
if (start < 0)
start = i; // new range starts
}
else if (start >= 0)
{
// range finished
result.Add((start, i - start));
start = -1;
}
}
if (start >= 0)
{
// orphan range at the end
result.Add((start, list.Count - start));
}
return result;
}
public static int RemoveIndexRanges<T>(this List<T> list,
List<(int start, int count)> ranges)
{
var removed = 0;
foreach (var range in ranges)
{
// the "- removed" is there to take into account
// that deletion moves the indexes.
list.RemoveRange(range.start - removed, range.count);
removed += range.count;
}
return removed;
}
Usage:
var ranges = list.GetIndexRanges((item, index) =>
{
//if (item == 10) throw new Exception();
return item % 2 == 1;
});
// See note 2 below
list.RemoveIndexRanges(ranges);
Note 1: As is, an exception in the predicate would just be propagated during the selection process, with no change to the ecollection. To give the caller more control over this, the following could be done: extend GetIndexRanges to still return everything collected so far, and in addition also return any exception as out parameter:
public static List<(int start, int count)> GetIndexRanges<T>(this List<T> list,
Func<T, int, bool> predicate, out Exception exception)
{
var result = new List<(int start, int count)>();
int start = -1;
for (var i = 0; i < list.Count; i++)
{
bool toBeRemoved = false;
try
{
toBeRemoved = predicate(list[i], i);
}
catch (Exception e)
{
exception = e;
break; // omit this line to continue with the selection process
}
if (toBeRemoved)
{
if (start < 0)
start = i; // new range starts
}
else if (start >= 0)
{
// range finished
result.Add((start, i - start));
start = -1;
}
}
if (start >= 0)
{
// orphan range at the end
result.Add((start, list.Count - start));
}
return result;
}
var ranges = list.GetIndexRanges((item, index) =>
{
if (item == 10) throw new Exception();
return item % 2 == 1;
}, out var exception);
// to fulfil requirement #3, we remove the ranges collected so far
// even in case of an exception
list.RemoveIndexRanges(ranges);
// and then throw the exception afterwards
if (exception != null)
ExceptionDispatchInfo.Capture(exception).Throw();
Note 2: As this is now a two-step process, it will fail if the list changes between the calls.
I think that I've managed to come up with an implementation that satisfies all three requirements:
/// <summary>
/// Removes all the elements that match the conditions defined by the specified
/// predicate. In case the predicate fails, the integrity of the list is preserved.
/// </summary>
public static int RemoveAll<T>(this List<T> list, Func<T, int, bool> predicate)
{
ArgumentNullException.ThrowIfNull(list);
ArgumentNullException.ThrowIfNull(predicate);
Span<T> span = CollectionsMarshal.AsSpan(list);
int i = 0, j = 0;
try
{
for (; i < span.Length; i++)
{
if (predicate(span[i], i)) continue;
if (j < i) span[j] = span[i];
j++;
}
}
finally
{
if (j < i)
{
for (; i < span.Length; i++, j++)
span[j] = span[i];
list.RemoveRange(j, span.Length - j);
}
}
return i - j;
}
For better performance it uses the CollectionsMarshal.AsSpan method (.NET 5) to get a Span<T> out of the list. The algorithm works just as well by using the indexer of the list instead of the span, and replacing the span.Length with list.Count.
Online demo.
I haven't benchmark this implementation, but I expect it to be only marginally slower than the native implementation.
So they don't think that there is any bug that needs to be fixed. They also believe that this behavior is not surprising or unexpected, so there is no need to document it.
They're correct. The method is documented as:
Removes all the elements that match the conditions defined by the specified predicate.
This supports two scenarios: the predicate returning true, removing an element, or false for leaving it as-is. A predicate throwing an exception is not a use case intended to be supported.
If you want to be able to pass a predicate that may throw, you could wrap it like this:
public static int RemoveAll<T>(this List<T> list, Func<T, int, bool> predicate)
{
Exception? caught = null;
int index = 0;
int removed = 0;
list.RemoveAll(item =>
{
// Ignore the rest of the list once thrown
if (caught != null) return false;
try
{
var remove = predicate(item, index);
if (remove)
{
removed++;
}
return remove;
}
catch (Exception e)
{
caught = e;
return false;
}
index++;
});
if (caught != null)
{
throw caught;
}
return removed;
}
I don't know microsoft is how to wrote this method.
I tried some code block. And i found case.
Actually problem is your throw new Exception(). If you dont this code that time yo code will run perfect. Exception trigger some another case. But i dont know what is that.
if (item >= 10) return false;
bool removeIt = item % 2 == 1;
if (removeIt) Console.WriteLine($"Removing #{item}");
return removeIt;
I found this. EDIT
Actually Func<T, int, bool> property is not deleted some item. It return boolean. As if return true he succesful deleted from list. If return false. it is not deleted from list.

Most efficient way to remove element of certain value everywhere from List? C#

EDIT: Benchmarks for different techniques published at the bottom of this question.
I have a very large List<int> full of integers. I want to remove every occurrence of "3" from the List<int>. Which technique would be most efficient to do this? I would normally use the .Remove(3) extension until it returns false, but I fear that each call to .Remove(3) internally loops through the entire List<int> unnecessarily.
EDIT: It was recommended in the comments to try
TheList = TheList.Where(x => x != 3).ToList();
but I need to remove the elements without instantiating a new List.
var TheList = new List<int> { 5, 7, 8, 2, 8, 3, 1, 0, 6, 3, 9, 3, 5, 2, 7, 9, 3, 5, 5, 1, 0, 4, 5, 3, 5, 8, 2, 3 };
//technique 1
//this technique has the shortest amount of code,
//but I fear that every time the Remove() method is called,
//the entire list is internally looped over again starting at index 0
while (TheList.Remove(3)) { }
//technique 2
//this technique is an attempt to keep the keep the list from
//being looped over every time an element is removed
for (var i = 0; i < TheList.Count; i++)
{
if (TheList[i] == 3)
{
TheList.RemoveAt(i);
i--;
}
}
Are there any better ways to do this?
Benchmarks
I tested three techniques to remove 10,138 from an array with 100,000 elements: the two shown above, and one recommended by Serg in an answer. These are the results:
'while' loop: 179.6808ms
'for' loop: 65.5099ms
'RemoveAll' predicate: 0.5982ms
Benchmark Code:
var RNG = new Random();
//inclusive min and max random number
Func<int, int, int> RandomInt = delegate (int min, int max) { return RNG.Next(min - 1, max) + 1; };
var TheList = new List<int>();
var ThreeCount = 0;
for (var i = 0; i < 100000; i++)
{
var TheInteger = RandomInt(0, 9);
if (TheInteger == 3) { ThreeCount++; }
TheList.Add(TheInteger);
}
var Technique1List = TheList.ToList();
var Technique2List = TheList.ToList();
var Technique3List = TheList.ToList();
<div style="background-color:aquamarine;color:#000000;">Time to remove #ThreeCount items</div>
//technique 1
var Technique1Stopwatch = Stopwatch.StartNew();
while (Technique1List.Remove(3)) { }
var Technique1Time = Technique1Stopwatch.Elapsed.TotalMilliseconds;
<div style="background-color:#ffffff;color:#000000;">Technique 1: #(Technique1Time)ms ('while' loop)</div>
//technique 2
var Technique2Stopwatch = Stopwatch.StartNew();
for (var i = 0; i < Technique2List.Count; i++)
{
if (Technique2List[i] == 3)
{
Technique2List.RemoveAt(i);
i--;
}
}
var Technique2Time = Technique2Stopwatch.Elapsed.TotalMilliseconds;
<div style="background-color:#ffffff;color:#000000;">Technique 2: #(Technique2Time)ms ('for' loop)</div>
//technique 3
var Technique3Stopwatch = Stopwatch.StartNew();
var RemovedCount = Technique3List.RemoveAll(x => x == 3);
var Technique3Time = Technique3Stopwatch.Elapsed.TotalMilliseconds;
<div style="background-color:#ffffff;color:#000000;">Technique 3: #(Technique3Time)ms ('RemoveAll' predicate)</div>
You can just use List<T>.RemoveAll and pass your predicate - https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1.removeall?view=net-6.0#System_Collections_Generic_List_1_RemoveAll_System_Predicate__0__ . This guaranteed to be linear complexity O(list.Count)
TheList.RemoveAll(x=>x==3);
Additionally, RemoveAll performs some GC-specific things internally, so I think in some cases this may provide some additional performance advantages against the simple hand-made loop implementation (but I'm unsure here).
If you want to do it all yourself, you can check out the implementation of RemoveAll here. Generally, it is just a while loop as in your question.
Additionally, as we can see from GitHub implementation (and as Jon Skeet mentioned in the comment) the remove operation causes the rest of list (all items after the first removed items) to be copied (shifted) on the free space, intorduced by deletion. So, if you have really huge list and/or want to remove something frequently, you may consider to switching to some other data structure, such as linked list.

Equivalent in C# to Haskell's Data.List.Span

Hello is there any efficient method implemented already to get the functionality of Haskell Data.List.span?
span :: (a -> Bool) -> [a] -> ([a], [a])
Basically given a list and a predicate i want to split the list in two after the first occurence of a false predicate.The elements after the pivot element that tests False may or may not respect the predicate , but I do not care.
List: [1,2,3,1,2,3]
Predicate: x<3
Span: `span (x<3) [1,2,3,1,2,3]` => `([1,2],[3,1,2,3])`
Update
I do not care of the elements after the first false predicate.I just want to split the list at the first occurence of False predicate. The sequence can be True after the first False predicate but I still want to split it.
If you are happy with using lists, then you can make a single pass through the source list to create two new lists, like so:
public static (List<T> part1, List<T> part2) SplitListBy<T>(List<T> source, Predicate<T> splitWhen)
{
var part1 = new List<T>();
int i;
for (i = 0; i < source.Count && !splitWhen(source[i]); ++i)
part1.Add(source[i]);
var part2 = source.GetRange(i, source.Count - i);
return (part1, part2);
}
This should be extremely performant. Note that this uses a tuple to return the two lists, which requires C# 7 or later. If you can't use c# 7+, you'll have to change the code to use an out parameter to return one of the lists.
Test code:
var list = new List<int>{ 1, 2, 3, 1, 2, 3 };
var (part1, part2) = SplitListBy(list, item => item >= 3);
Console.WriteLine(string.Join(", ", part1));
Console.WriteLine(string.Join(", ", part2));
Output:
1, 2
3, 1, 2, 3
If you don't need two new lists, but just want to use the original list for one part and a single new list for the other part, you can do it like this:
public static List<T> SplitListBy<T>(List<T> source, Predicate<T> splitWhen)
{
int i;
for (i = 0; i < source.Count && !splitWhen(source[i]); ++i)
;
var part2 = source.GetRange(i, source.Count - i);
source.RemoveRange(i, source.Count - i);
return part2;
}
Test code for this is very similar:
var list = new List<int>{ 1, 2, 3, 1, 2, 3 };
var part2 = SplitListBy(list, item => item >= 3);
Console.WriteLine(string.Join(", ", list));
Console.WriteLine(string.Join(", ", part2));
(Output is the same as the other test code.)
You could make use of TakeWhile and Skip:
public static IEnumerable<IEnumerable<T>> SplitWhen<T>(this IEnumerable<T> enumerable, Func<T, bool> predicate)
{
var first = enumerable.TakeWhile(predicate);
yield return first;
var second = enumerable.Skip(first.Count());
yield return second;
}
Update
To avoid multiple iterations, and not requiring the use of a list or array:
public static IEnumerable<IEnumerable<T>> SplitWhen<T>(this IEnumerable<T> enumerable, Func<T, bool> predicate)
{
yield return enumerable.TakeWhile(predicate);
yield return enumerable.TakeAfter(predicate);
}
public static IEnumerable<T> TakeAfter<T>(this IEnumerable<T> enumerable, Func<T, bool> predicate)
{
bool yielding = false;
foreach (T item in enumerable)
{
if (yielding = yielding || !predicate(item))
{
yield return item;
}
}
}
At the time that I'm writing this answer, I don't think that any of the other answers faithfully replicate Haskell's span function. That's okay, you may actually be looking for something else, but I wanted to add this for completion's sake.
First, you can't necessarily assume that span only iterates over the input list once. It's difficult to reason about Haskell's run-time behaviour because of its lazy evaluation, but consider this list:
xs = [trace "one" 1, trace "two" 2, trace "three" 3,
trace "one" 1, trace "two" 2, trace "three" 3]
Here I've deliberately used trace from Debug.Trace so that we can observe what's going on. Specifically, I want to point your attention to what happens if you iterate over the lists independently, as one would probably do in 'real' code:
Prelude Data.List Debug.Trace> (l, r) = span (< 3) xs
Prelude Data.List Debug.Trace> l
one
[1two
,2three
]
Iterating over the first list stops at the first value that evaluates to False, so that's fine and efficient. That's not the case, however, when you print the second list:
Prelude Data.List Debug.Trace> r
one
two
three
[3,one
1,two
2,three
3]
Notice that while it only prints [3, 1, 2, 3], it iterates over the entire list. How could it do otherwise? It's a function. It doesn't maintain a bookmark over how far it's already iterated the list.
On the other hand, the function does handle infinite lists:
Prelude Data.List> take 10 $ fst $ span (< 3) $ repeat 1
[1,1,1,1,1,1,1,1,1,1]
Prelude Data.List> take 10 $ fst $ span (< 3) $ repeat 3
[]
Prelude Data.List> take 10 $ snd $ span (< 3) $ repeat 3
[3,3,3,3,3,3,3,3,3,3]
As far as I can tell, few of the other answers (as I'm writing this) handle infinite lists.
In C#, lazily evaluated lists are modelled with IEnumerable<T>, so the best I've been able to come up with is this:
public static (IEnumerable<T>, IEnumerable<T>) Span<T>(
this IEnumerable<T> source,
Func<T, bool> pred)
{
return (source.TakeWhile(pred), source.SkipWhile(pred));
}
which, admittedly, is hardly above the Fairbairn threshold. It does, however, handle infinite sequences in the same way as span does:
> var (left, right) = new[] { 1, 2, 3, 1, 2, 3 }.Span(x => x < 3);
> left
TakeWhileIterator { 1, 2 }
> right
SkipWhileIterator { 3, 1, 2, 3 }
> var (left, right) = 1.RepeatInfinite().Span(x => x < 3);
> left.Take(10)
TakeIterator { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
> var (left, right) = 3.RepeatInfinite().Span(x => x < 3);
> right.Take(10)
TakeIterator { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }
> left.Take(10)
TakeIterator { }
I don't think there is a native .NET Framework or .NET Core method that does this, so you'll probably have to write your own. Here is my extension method implementation of this:
public static Tuple<IEnumerable<T>, IEnumerable<T>> SplitWhen<T>(this IEnumerable<T> self, Func<T, bool> func)
{
// Enumerate self to an array so we don't do it multiple times
var enumerable = self as T[] ?? self.ToArray();
var matching = enumerable.TakeWhile(func).ToArray();
var notMatching = enumerable.Skip(matching.Length);
return new Tuple<IEnumerable<T>, IEnumerable<T>>(matching, notMatching);
}
This method will return a tuple with tuple.Item1 being the part of the list that matches the predicate, and tuple.Item2 being the rest of the list.
This method needs to be declared in a separate static class as it is an extension method for IEnumerable<T>. You can also use Tuple construction/ deconstruction if you want to name Item1 and Item2 something different
the simplest way to use ToLookup
example
var listInt = new List<int>{1, 2, 3, 4, 5, 6};
var result = listInt.ToLookup(x => x > 3);
Result
[[1,2,3], [4,5,6]]
Edit
var listInt = new List<int> { 1, 2, 3, 1, 2, 3 };
Create an extension method
public static IEnumerable<T> TakeUntil<T>(this IEnumerable<T> source, Func<T, bool> predicate)
{
foreach (var item in source)
{
if (!predicate(item))
break;
yield return item;
}
}
and call it
var first = listInt.TakeUntil(x => x < 3);
var second = listInt.Skip(first.Count());
Result
first = [1,2]
second = [3, 1, 2, 3]
I believe you are looking for a c# IEnumerable. You could write for example
IEnumerable<int> list = new List<int> { 1,2,3,4,5,6};
var list1 = list.Where(x=>x>3); //deferred execution
var list2 = list.Where(x=>x<=3); //deferred execution
I have accepted #Matthew Watson solution.Though i will also post a little modified version using the Span and ReadOnlyMemory
public static (IEnumerable<T>first,IEnumerable<T> second) Span<T>(this ReadOnlyMemory<T> original,Func<T,bool> predicate) {
List<T> list = new List<T>();
int splitIndex = 0;
for (int i = 0; i < original.Length && !predicate(original.Span[i]); i++) {
list.Add(original.Span[splitIndex=i]);
}
var part2 = original.Slice(splitIndex);
return (list, part2.ToArray());
}

C# Collection - Order by an element (Rotate)

I have an IEnumerable<Point> collection. Lets say it contains 5 points (in reality it is more like 2000)
I want to order this collection so that a specifc point in the collection becomes the first element, so it's basically chopping a collection at a specific point and rejoining them together.
So my list of 5 points:
{0,0}, {10,0}, {10,10}, {5,5}, {0,10}
Reordered with respect to element at index 3 would become:
{5,5}, {0,10}, {0,0}, {10,0}, {10,10}
What is the most computationally efficient way of resolving this problem, or is there an inbuilt method that already exists... If so I can't seem to find one!
var list = new[] { 1, 2, 3, 4, 5 };
var rotated = list.Skip(3).Concat(list.Take(3));
// rotated is now {4, 5, 1, 2, 3}
A simple array copy is O(n) in this case, which should be good enough for almost all real-world purposes. However, I will grant you that in certain cases - if this is a part deep inside a multi-level algorithm - this may be relevant. Also, do you simply need to iterate through this collection in an ordered fashion or create a copy?
Linked lists are very easy to reorganize like this, although accessing random elements will be more costly. Overall, the computational efficiency will also depend on how exactly you access this collection of items (and also, what sort of items they are - value types or reference types?).
The standard .NET linked list does not seem to support such manual manipulation but in general, if you have a linked list, you can easily move around sections of the list in the way you describe, just by assigning new "next" and "previous" pointers to the endpoints.
The collection library available here supports this functionality: http://www.itu.dk/research/c5/.
Specifically, you are looking for LinkedList<T>.Slide() the method which you can use on the object returned by LinkedList<T>.View().
Version without enumerating list two times, but higher memory consumption because of the T[]:
public static IEnumerable<T> Rotate<T>(IEnumerable<T> source, int count)
{
int i = 0;
T[] temp = new T[count];
foreach (var item in source)
{
if (i < count)
{
temp[i] = item;
}
else
{
yield return item;
}
i++;
}
foreach (var item in temp)
{
yield return item;
}
}
[Test]
public void TestRotate()
{
var list = new[] { 1, 2, 3, 4, 5 };
var rotated = Rotate(list, 3);
Assert.That(rotated, Is.EqualTo(new[] { 4, 5, 1, 2, 3 }));
}
Note: Add argument checks.
Another alternative to the Linq method shown by ulrichb would be to use the Queue Class (a fifo collection) dequeue to your index, and enqueue the ones you have taken out.
The naive implementation using linq would be:
IEnumerable x = new[] { 1, 2, 3, 4 };
var tail = x.TakeWhile(i => i != 3);
var head = x.SkipWhile(i => i != 3);
var combined = head.Concat(tail); // is now 3, 4, 1, 2
What happens here is that you perform twice the comparisons needed to get to your first element in the combined sequence.
The solution is readable and compact but not very efficient.
The solutions described by the other contributors may be more efficient since they use special data structures as arrays or lists.
You can write a user defined extension of List that does the rotation by using List.Reverse(). I took the basic idea from the C++ Standard Template Library which basically uses Reverse in three steps: Reverse(first, mid) Reverse(mid, last) Reverse(first, last)
As far as I know, this is the most efficient and fastest way. I tested with 1 billion elements and the rotation Rotate(0, 50000, 800000) takes 0.00097 seconds. (By the way: adding 1 billion ints to the List already takes 7.3 seconds)
Here's the extension you can use:
public static class Extensions
{
public static void Rotate(this List<int> me, int first, int mid, int last)
{
//indexes are zero based!
if (first >= mid || mid >= lastIndex)
return;
me.Reverse(first, mid - first + 1);
me.Reverse(mid + 1, last - mid);
me.Reverse(first, last - first + 1);
}
}
The usage is like:
static void Main(string[] args)
{
List<int> iList = new List<int>{0,1,2,3,4,5};
Console.WriteLine("Before rotate:");
foreach (var item in iList)
{
Console.Write(item + " ");
}
Console.WriteLine();
int firstIndex = 0, midIndex = 2, lastIndex = 4;
iList.Rotate(firstIndex, midIndex, lastIndex);
Console.WriteLine($"After rotate {firstIndex}, {midIndex}, {lastIndex}:");
foreach (var item in iList)
{
Console.Write(item + " ");
}
Console.ReadKey();
}

How to select values within a provided index range from a List using LINQ

I am a LINQ newbie trying to use it to acheive the following:
I have a list of ints:-
List<int> intList = new List<int>(new int[]{1,2,3,3,2,1});
Now, I want to compare the sum of the first three elements [index range 0-2] with the last three [index range 3-5] using LINQ. I tried the LINQ Select and Take extension methods as well as the SelectMany method, but I cannot figure out how to say something like
(from p in intList
where p in Take contiguous elements of intList from index x to x+n
select p).sum()
I looked at the Contains extension method too, but that doesn't see to get me what I want. Any suggestions? Thanks.
Use Skip then Take.
yourEnumerable.Skip(4).Take(3).Select( x=>x )
(from p in intList.Skip(x).Take(n) select p).sum()
You can use GetRange()
list.GetRange(index, count);
For larger lists, a separate extension method could be more appropriate for performance. I know this isn't necessary for the initial case, but the Linq (to objects) implementation relies on iterating the list, so for large lists this could be (pointlessly) expensive. A simple extension method to achieve this could be:
public static IEnumerable<TSource> IndexRange<TSource>(
this IList<TSource> source,
int fromIndex,
int toIndex)
{
int currIndex = fromIndex;
while (currIndex <= toIndex)
{
yield return source[currIndex];
currIndex++;
}
}
Starting from .NET 6 it is possible to use range syntax for Take method.
List<int> intList = new List<int>(new int[]{1, 2, 3, 3, 2, 1});
// Starting from index 0 (including) to index 3 (excluding) will select indexes (0, 1, 2)
Console.WriteLine(intList.Take(0..3).Sum()); // {1, 2, 3} -> 6
// By default is first index 0 and can be used following shortcut.
Console.WriteLine(intList.Take(..3).Sum()); // {1, 2, 3} -> 6
// Starting from index 3 (including) to index 6 (excluding) will select indexes (3, 4, 5)
Console.WriteLine(intList.Take(3..6).Sum()); // {3, 2, 1} -> 6
// By default is last index lent -1 and can be used following shortcut.
Console.WriteLine(intList.Take(3..).Sum()); // {3, 4, 5} -> 6
// Reverse index syntax can be used. Take last 3 items.
Console.WriteLine(intList.Take(^3..).Sum()); // {3, 2, 1} -> 6
// No exception will be raised in case of range is exceeded.
Console.WriteLine(intList.Take(^100..1000).Sum());
So simply put, intList.Take(..3).Sum() and intList.Take(3..).Sum() can be used with .NET 6.
To filter by specific indexes (not from-to):
public static class ListExtensions
{
public static IEnumerable<TSource> ByIndexes<TSource>(this IList<TSource> source, params int[] indexes)
{
if (indexes == null || indexes.Length == 0)
{
foreach (var item in source)
{
yield return item;
}
}
else
{
foreach (var i in indexes)
{
if (i >= 0 && i < source.Count)
yield return source[i];
}
}
}
}
For example:
string[] list = {"a1", "b2", "c3", "d4", "e5", "f6", "g7", "h8", "i9"};
var filtered = list.ByIndexes(5, 8, 100, 3, 2); // = {"f6", "i9", "d4", "c3"};

Categories