C#8.0有關陣列index中的"點點"運算子
先來一個單元測試範例
int[] a = new int[] { 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
// StartAt 2,EndAt 5 (不包含5)
Assert.AreEqual(a[2..5], new int[] { 7, 8, 9 });
Assert.AreEqual(a[new Range(new Index(2), new Index(5))], new int[] { 7, 8, 9 });
a[2..5]中的2..5代表一個Range,可用來取出指定Index範圍的集合
2與5分別代表著Index,Index可由前開始或由後開始,如果由後開始可加上^運算子,array[^x] 會被轉為 array[array.Length - x]
所以fromEnd(由後開始)時最後一個元素是array[^1]
fromEnd範例如下
int[] a = new int[] { 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
// FromEnd
Assert.AreEqual(a[2..^2], new int[] { 7, 8, 9, 10, 11, 12, 13 });
// 因為轉換機制是array.Length - x,^0寫在Range的End時是沒問題,一旦取到就是Index out of bound
// a[^0] thorws Exception
Assert.AreEqual(a[^11], 5);
Assert.AreEqual(a[^1], 15);
index範例
array: { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' }
index: 0, 1, 2, 3, 4, 5, 6, 7
fromEnd: ^8, ^7, ^6, ^5, ^4, ^3, ^2, ^1
而Range寫為expr1..expr2,其中expr1、expr2可省略
如果省略了expr1,就相當於0..expr2,類似SkipLast概念
如果省略了expr2,就相當於expr1..^0,類似Skip概念
如果都省略了(只剩下..),就相當於0..^0 (Range.All)
配上Linq的Append、Prepend,循環左移、循環右移也可以更簡短了
int[] a = new int[] { 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
// RightShift
Assert.AreEqual(a[..^1].Prepend(a[^1]), new int[] { 15, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 });
// LeftShift
Assert.AreEqual(a[1..].Append(a[0]), new int[] { 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 5 });
參考:
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/ranges