zoukankan      html  css  js  c++  java
  • 在C#中实现Python的分片技术

    在C#中实现Python的分片技术

    前言

      之前在学习Python的时候发现Python中的分片技术超好玩的,本人也是正则表达式热爱狂,平时用C#比较多,所以决定把Python中的分片技术在C#中实现,添加到个人类库中,以便日后在写C#代码的时候能舔一舔Python的味道。

    效果展示

                 Python版:           C#版:

    切割技术讲解

      这里先简要讲解一下Python中的分片技术,其他Python前辈也对此技术有丰富多彩的讲解文章,这里只是简要说明一下,好让读者们能知道下怎么回事,如果想更深入了解Python的分片技术,这里并不适合你哦。

      分片的对象可以是字符串或者序列,本文提供字符串的实现方法,其实序列差不多的,我也会在最后提供字符串和序列的实现代码,并且附带单元测试。

      好了,废话不多说,其实看了上面的Python版的结果,我想聪明的您就略知一二了。分片的模板是:变量[起始位置:终点位置:步长],举个例子:a="abcdfeghij",那么a[0:2:1]这个的结果就是零位置开始(a的左边),步长为1(也就是连续取),到2位置结束(从a的左边开始:0->(a的左边),1->(b的左边,a的右边),2->(c的左边,b的右边)->结束),好了,结果就是"ab"。

           注意事项:1.步长可以忽略不写(默认为1),如果步长为2,就每取一个跳过1个,以此类推。

                2.可以使用负数a[-3:-1:1],结果是"ef",读者们可以自己推一下,很简单。

                3.分片技术可以针对字符串,也可以针对序列。

      

    实现过程

      这里需要用到正则表达式的技术,可能对一些朋友来说比较难懂,但是我会尽量讲解的简单一点。

      首先,要使用分片,有三个参数可以控制:起始位置,结束位置,步长。所以在正则表达式应该嵌入这三个参数变量,在匹配的时候动态生成正则表达式。下面来看需要把这三个参数放到哪里:

        起始位置:

            1.背景

                这里使用肯定逆序环视,什么是肯定逆序环视,就是匹配到的位置那一点向后看,向后看的内容必须符合环视的内容,举个例子:文本:abc  ,正则表达式:(?<=a)b,肯定逆序环视符号:(?<=exp),这个正则表达式的意思就是找到b,然后向后看(左边),如果a就匹配成功,结果就是b(因为逆序环视是不纳入结果中)。

              2.实现

                我使用[sS]来表示一个任意符号,含有位置参数的部分放到左边,形成这样一个正则表达式:

    (?<=^[sS]{StarIndex,})[sS]  注意这里的StarIndex是变量,可以是0,1,2,3..!以StarIndex=2(其实位置是2)为例,匹配一个任意字

    符,并且向后看(左边)是开头->2个或者多个任意字符。

        结束位置:

             1.背景

                这里使用肯定顺序环视,什么是肯定顺序环视,就是匹配到的位置那一点向前看,向前看的内容必须符合环视的内容,举个例子:文本abc ,正则表达式:(?=b)a,肯定逆序环视符号:(?=exp),这个正则表达式的意思就是找到a,然后向前看(右边),如果是b就匹配成功,结果就是a(因为顺序环视是不纳入结果中)。

             2.实现

                有了前面表达式基础,我需要在后面添加一个顺序环视,形成这样一个表达式(合并过后):

    (?<=^[sS]{StarIndex,})[sS](?=[sS]{EndCount}),这里要注意了,EndCount并不是结束位置,计算公式:

    EndCount=String.Length-EndIndex。字符串长度-结束位置。

        步长:

           最后终于到步长了,这是关键的一步,用于连接上面两部的,其实基础前面已经讲了,下面给出加入步长逻辑以后,形成的最后正则表达式:(?<=^[sS]{StarIndex,})(?<=^[sS]{MiddleCount})[sS](?=[sS]{EndCount}),步长参数为Step变量,这里的MiddleCount在循环中改变,每次循环都MiddleCount=MiddleCount+Step;循环到最后合并获取到的字符形成结果字符串!!。

    实例演示

        最后演示一下具体匹配实例,过程,结果。

        字符串:a="abcdefghij";  a.Cut(0,3,1);

            循环次数:3-0=3次。

    循环一:表达式:(?<=^[sS]{0,})(?<=^[sS]{0})[sS](?=[sS]{7})

          结果图:  =====》'a'

    循环二:表达式(?<=^[sS]{0,})(?<=^[sS]{1})[sS](?=[sS]{7})

         结果图:=====》'b'

    循环三:表达式(?<=^[sS]{0,})(?<=^[sS]{2})[sS](?=[sS]{7})

         结果图:=====》'c' 

        最终合并结果:"abc"。最后贴一张Python中的结果:.

    代码展示

      

    public static class StringExpander
        {
            /// <summary>
            /// Python中的字符串切片技术,[开始索引:结束索引:步长值]
            /// </summary>
            /// <param name="Str">目标字符串</param>
            /// <param name="StarIndex">开始索引</param>
            /// <param name="EndIndex">结束索引</param>
            /// <param name="Step">步长值</param>
            /// <returns></returns>
            public static String StringCut(this String Str, Int32 StarIndex, Int32 EndIndex, Int32 Step = 1)
            {
                if (EndIndex < 0)
                { EndIndex = Str.Length + EndIndex; }
                if (StarIndex < 0)
                { StarIndex = Str.Length + StarIndex; }
                StringBuilder sb = new StringBuilder();
                Int32 LoopTime = EndIndex - StarIndex;
                if (EndIndex > Str.Length) { EndIndex = Str.Length; }
                Int32 EndCount = Str.Length - EndIndex;
                int j = StarIndex;
                for (int i = 0; i < LoopTime; i = i + Step)
                {
                    String RegexString = @"(?<=^[sS]{" + StarIndex + @",})(?<=^[sS]{" + j + @"})[sS](?=[sS]{" + EndCount + @"})";
                    try
                    {
                        sb.Append(Regex.Match(Str, RegexString).Value);
                    }
                    catch { }
                    j = j + Step;
                }
                return sb.ToString();
            }
            /// <summary>
            /// Python中的字符串切片技术,只提供位置
            /// </summary>
            /// <param name="Str">目标字符串</param>
            /// <param name="StarIndex">位置</param>
            /// <returns></returns>
            public static String StringCut(this String Str, Int32 StarIndex)
            {
                if (StarIndex < 0)
                { StarIndex = Str.Length + StarIndex; }
                return Str.Substring(StarIndex, 1);
            }
        }

    总结

      现在提供的是字符串的实现方法,在下面可以下载Demo,里面有序列的实现方法,思想差不多,但是需要添加点东西。谢谢大家观看!

      

                    源码下载

  • 相关阅读:
    论自己电脑如何搭建服务器
    nodejs + express + art-template + mongodb简单项目
    npm和yarn使用
    Linux内核编译
    Linux 网络编程
    Linux进程管理
    LeetCode1576. 替换所有的问号
    LeetCode392. 判断子序列
    LeetCode674. 最长连续递增序列
    剑指 Offer 48. 最长不含重复字符的子字符串
  • 原文地址:https://www.cnblogs.com/Jarvin/p/3721728.html
Copyright © 2011-2022 走看看