Currently I'm sort of playing with this new c# 8.0
feature which is ranges.
And so far I have a question. Am I allowed to create a range
from the end to the beginning ?
Lets say I have an array
and I would like to print it out in reversed direction via range
:
static void Test()
{
int[] array = new int[10];
for (int i = 0; i < 10; i++) array[i] = i;
Range range = ^1..0;
foreach (int v in array[range]) WriteLine(v);
}
But it gets me a runtime error - System.OverflowException: 'Arithmetic operation resulted in an overflow.'
So am I right that the only one direction(from the beginning to the end) is allowed for ranges
?
If you wrap range() inside reversed() , then you can print the integers in reverse order. range() makes it possible to iterate over a decrementing sequence of numbers, whereas reversed() is generally used to loop over a sequence in reverse order. Note: reversed() also works with strings.
To print an array in reverse order, we shall know the length of the array in advance. Then we can start an iteration from length value of array to zero and in each iteration we can print value of array index. This array index should be derived directly from iteration itself.
reverse() method! The built-in reversed() function reverses the order of a list and lets you access each individual item one at a time. The reversed() function accepts a list as an argument and returns an iterable, reversed version of the items contained in the list.
Q. Program to print the elements of an array in reverse order. In this program, we need to print the elements of the array in reverse order that is; the last element should be displayed first, followed by second last element and so on. Above array in reversed order: Declare and initialize an array.
However, unlike other programming languages, arrays aren't a built-in data structure in Python. Instead, you use lists, and Python offers a few ways to reverse them. Using this built-in Python method, the list changes in place. This means that the original order of the list is affected. The initial order of the items gets updated and altered.
Notice that the reverse of Python range is simplifying creating a new range but this time the last element of the previous range will be the first element and will return all other elements in reverse order. What is the Python range () method? Before going into the reverse of the Python range, first, let us understand the range () method.
Algorithm 1 START 2 INITIALIZE arr [] = {1, 2, 3, 4, 5} 3 PRINT "Original Array:" 4 REPEAT STEP 5 for (i=0; i<arr.length ; i++) 5 PRINT arr [i] 6 PRINT "Array in reverse order" 7 REPEAT STEP 8 for (i= arr.length-1; i>=0; i--) 8 PRINT a [i] 9 END
Reverse ranges are not so much a limitation on the Range
type, but rather a limitation on the Span
(and related) types – which assume a positive increment. The rational is that many of the low-level optimizations and usage scenarios for a slice of an array are only geared toward the basic notion of a "pointer plus size". (Link to Range usages in Framework)
While this won't allow a reverse Span
to be passed around, an extension method could be used to provide an easy and performant syntax for reverse range enumeration:
public static class RangeExtensions
{
public static int Normalize(this Index index, int length) =>
index.IsFromEnd ? length - index.Value : index.Value;
public static (int start, int end) Normalize(this Range range, int length) =>
(range.Start.Normalize(length), range.End.Normalize(length));
public static IEnumerable<T> Enumerate<T>(this T[] items, Range range)
{
var (start, end) = range.Normalize(items.Length);
return start <= end ? items[range] : GetRangeReverse();
IEnumerable<T> GetRangeReverse()
{
for (int i = start; i >= end; i--)
yield return items[i];
}
}
}
...
var numbers = Enumerable.Range(0, 10).ToArray();
foreach (var num in numbers.Enumerate(^3..1))
Console.WriteLine(num);
I couldn't find anything that says that's possible. But, it doesn't appear to be a language restriction, as we can create a range like Range r = 5..1;
and that doesn't throw exceptions, so it must be the implementation of Array[Range]
and other types, like string that doesn't accept it. That put, you can probably create an method that accepts a Range
and does what you want.
Edit: I made the following method that works with arrays:
static T[] MySlice<T>(T[] array, Range r)
{
//Transforms indexes "from end" to indexes "from start"
if(r.Start.IsFromEnd){
var startIdx = array.Length - r.Start.Value;
r = new Range(startIdx,r.End);
}
if(r.End.IsFromEnd){
var endIdx = array.Length - r.End.Value;
r = new Range(r.Start,endIdx);
}
//Check if start value is greater than end value. If so, invert it
if(r.Start.Value > r.End.Value)
{
r = new Range(r.End,r.Start);
var invArr = array[r];
Array.Reverse(invArr);
return invArr;
}
return array[r];
}
And you can use like
int[] arr = Enumerable.Range(0,10).ToArray();
Range r = ^0..0;
foreach(var v in MySlice(arr,r)){
Console.WriteLine(v);
}
Which outputs:
9
8
7
6
5
4
3
2
1
0
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With