c# Range/Index范围和索引

  • Span
    C# 7 里面出现了Span这个数据类型,它可以表示另一个数据结构里连续相邻的一串数据,并且它是内存安全的
static void TestSpan()
{
    //var arr = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    var arr = Enumerable.Range(1, 10).ToArray();
    Span<int> slice = arr.AsSpan().Slice(2, 4);
    Console.WriteLine(string.Join(",", slice.ToArray()));
}
//返回3,4,5,6
```c#
- Range
而C# 8里面我们可以从一个序列里面很简单的提取出来一个子范围组成新的序列。
```c#
int[] someArray = Enumerable.Range(1, 5).ToArray();
int[] subArray1 = someArray[0..2];//{1,2}
Console.WriteLine(string.Join(",", subArray1));
//返回1,2

这里面使用了范围运算符..
arr[2..4]表示把arr这个序列,从索引为2的元素一直到索引为4(但不包括索引4)的元素提取出来组成新的序列。所以结果就是3,4
更多Range例子:

//int[] someArray = new int[5] { 1, 2, 3, 4, 5 };
int[] someArray = Enumerable.Range(1, 5).ToArray();
int[] subArray1 = someArray[0..2];//{1,2}
Console.WriteLine(string.Join(",", subArray1));
int[] subArray2 = someArray[1..^0];//{2,3,4,5}
Console.WriteLine(string.Join(",", subArray2));
int[] subArray3 = someArray[1..];
Console.WriteLine(string.Join(",", subArray3));

List<int> otherArray = new List<int> { 1, 2, 3, 4, 5 };
int[] other1 = otherArray.ToArray()[1..2];

//创建Range对象
//var arr = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var arr = Enumerable.Range(1, 10).ToArray();
Index middle = 4;
Index threeFromEnd = ^3;//Hat运算符^
Range range = middle..threeFromEnd;
int[] slice = arr[range];
Console.WriteLine(string.Join(",", slice));

//使用Index类型和^操作符
Index index = ^2;
var number = arr[index];
Console.WriteLine(number);//9

//使用Range和Index
var arrTwin = arr[0..^0];//arrTwin是arr的完成拷贝
foreach (var i in arrTwin)
{
    Console.WriteLine(i);
}

var arrTwin2 = arr[..];//arr[0..^0];的简化版, 还等同于 arr[0..10];
foreach (var i in arrTwin2)
{
    Console.WriteLine(i);
}

int[] arrTwin3 = arr[..];//完成的复制,数组
int[] allButFirst = arr[1..];//不包含第一个元素的数组
int[] empty = arr[^0..];//空数组
int[] onlyLastItem = arr[^1..];//只包含最后一个元素的数组
int[] last4Items = arr[^4..];//包含四个元素的数组
int lastItem = arr[^1];//最后一个元素,类型是int
  • Range操作二维数组
    循环访问位于中心的节,不包括前三行和后三行,以及每个选定行中的前两列和后两列:
static void TestRange2()
{
    var jagged = new int[10][]{
        new int[10] { 0,  1, 2, 3, 4, 5, 6, 7, 8, 9},
        new int[10] { 10,11,12,13,14,15,16,17,18,19},
        new int[10] { 20,21,22,23,24,25,26,27,28,29},
        new int[10] { 30,31,32,33,34,35,36,37,38,39},
        new int[10] { 40,41,42,43,44,45,46,47,48,49},
        new int[10] { 50,51,52,53,54,55,56,57,58,59},
        new int[10] { 60,61,62,63,64,65,66,67,68,69},
        new int[10] { 70,71,72,73,74,75,76,77,78,79},
        new int[10] { 80,81,82,83,84,85,86,87,88,89},
        new int[10] { 90,91,92,93,94,95,96,97,98,99},
    };
    var selectedRows = jagged[3..^3];
    foreach (var row in selectedRows)
    {
        var selectedColumns = row[2..^2];
        foreach (var cell in selectedColumns)
        {
            Console.WriteLine($"{cell}, ");
        }
        Console.WriteLine();
    }
}

  • Range的应用场景
    要分析较大序列的子范围时,通常会使用范围和索引。 在准确读取所涉及的子范围这一方面,新语法更清晰。 本地函数 MovingAverageRange 为参数。 然后,该方法在计算最小值、最大值和平均值时仅枚举该范围。
static void TestRange3()
{
    //同时返回多个值
    (int min, int max, double average) MovingAverage(int[] subSequence, Range range) => (
        subSequence[range].Min(),
        subSequence[range].Max(),
        subSequence[range].Average()
        );
    int[] Sequence(int count) => Enumerable.Range(0, count).Select(x => (int)(Math.Sqrt(x) * 100)).ToArray();
    int[] sequence = Sequence(1000);
    for (int start = 0; start < sequence.Length; start += 100)
    {
        Range r = start..(start + 10);
        var (min, max, average) = MovingAverage(sequence, r);
        Console.WriteLine($"From {r.Start} to {r.End}: \tMin: {min},\t{max},\tAverage: {average}");
    }

    for (int start = 0; start < sequence.Length; start += 100)
    {
        Range r = ^(start + 10)..^start;
        var (min, max, average) = MovingAverage(sequence, r);
        Console.WriteLine($"From {r.Start} to {r.End}:  \tMin: {min},\tMax: {max},\tAverage: {average}");
    }
}

总结:

  • Range类型;
    一定要注意Range的范围包括Start不包括End。
    Range运算符:..
    Range应用场景:分析较大序列的子范围时,通常会使用范围和索引,语法更清晰
  • Index类型;
    从头开始的索引是从0开始的
    从尾部开始的索引是从1开始的,与序列的长度相关。
  • Hat 运算符:^
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,830评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,992评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,875评论 0 331
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,837评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,734评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,091评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,550评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,217评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,368评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,298评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,350评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,027评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,623评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,706评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,940评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,349评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,936评论 2 341

推荐阅读更多精彩内容

  • Win7下如何打开DOS控制台? a:开始--所有程序--附件--命令提示符 b:开始--搜索程序和文件--cmd...
    逍遥叹6阅读 1,584评论 4 12
  • 概要 64学时 3.5学分 章节安排 电子商务网站概况 HTML5+CSS3 JavaScript Node 电子...
    阿啊阿吖丁阅读 9,039评论 0 3
  • 2.变量和基本类型 3.字符串、向量和数组 4.表达式 5.语句 2.变量和基本类型 c++的算术类型: 一个ch...
    暮落晴空阅读 636评论 0 0
  • 基础 .NET概述 参考:http://www.cnblogs.com/yplong/p/3279934.html...
    donite阅读 1,608评论 0 8
  • Comment your JavaScript Code JavaScript中的注释方式有以下两种: 使用 //...
    归云丶阅读 1,088评论 0 0