1. 程式人生 > >根據指定字符集拆分任意字串

根據指定字符集拆分任意字串

題目真不知道怎麼寫。。我經常自己做一些小工具,所以並沒啥系統的東西可寫,這也並不是我想寫系統的東西,而且看別人寫的高大上的東西我也一點都不羨慕,真的哭

具體是這樣,有一個列表,裡面存放的是一些不重複的字元,假定這些字元就是我需要找出的,或者說在我這個工具中,我需要在一個任意字串中分別找出字元列表中有的和沒有的,並拆分成小的字串。說著這麼多,我成功把自己說糊塗了。

舉個栗子更好說明我的意圖:

//指定的字符集
char[] data = new char[]
{
    'a', 'c', 'e'
};

然後有個任意字串:
string input = "eadshafajhkjacccacaesdmf";

我要做的就是將其拆分為:
ea
dsh
a
f
a
jhkj
acccacae
sdmf

oh, this is so boring. 

同事對我的評價基本都是“喜歡把簡單的事情複雜化”。

接下來就開始介紹我是如何把簡單的事情複雜化的。

(tips:以下程式碼片段均以減慢執行速度、佔用更多記憶體、降低程式效能為目的進行編寫的得意

首先獲取指定列表中不存在的字元在給定字串中的位置

        /// <summary>
        /// 獲取指定列表中不存在的字元在給定字串中的位置
        /// </summary>
        /// <param name="input">給定的字串</param>
        /// <param name="source">指定的列表</param>
        public List<int> GetFailedLocations(string input, char[] source)
        {
            if (string.IsNullOrEmpty(input))
            {
                return null;
            }
            List<int> failedLocs = new List<int>();
            try
            {
                List<char> failedtemp = new List<char>();//為了增加記憶體佔用,建立一個存放已找出的不存在的字符集快取
                int index = 0;
                foreach (var value in input)
                {
                    if (failedtemp.Contains(value))
                    {
                        failedLocs.Add(index);
                    }
                    else
                    {
                        if (!source.Contains(value))
                        {
                            failedtemp.Add(value);
                            failedLocs.Add(index);
                        }
                    }
                    index++;
                }
            }
            catch { throw; }
            return failedLocs;
        }

新建一個類用來存放分類之後的字串資訊:
    public class Sentence
    {
        public int Order { get; set; }//在原始字串中的次序
        public string Data { get; set; }//分割出的字串資訊
        public bool Failed { get; set; }//是否在指定字符集中存在

        public override string ToString()
        {
            return this.Data;
        }
    }

這裡要說明的是,如果在給定的字串中,有連續多個字元在指定的字符集中存在,那就把它們連線成一個字串而不是單個字元。

然後,

如果全部都存在,即之前得到的存放不存在字元序號的列表數量為0,那麼就原樣放進類中

       Sentence sentence = new Sentence()
       {
           Order = 0,
           Data = input,
           Failed = false
       };

否則進行如下處理:

獲取在給定字串中不存在的【連續】字元的起始位置及長度:

       //startindex, length
       Dictionary<int, int> loctemp = new Dictionary<int, int>();
       int index = -1;
       int lastloc = -1;
       foreach (var loc in failedLocs)
       {
           if (loc != index)
           {
               loctemp.Add(loc, 1);
               index = loc;
               lastloc = loc;
           }
           else
           {
               loctemp[lastloc]++;
           }
           index++;
       }

上面這些程式碼有點繞,如果同事們看了一定又要說:我靠!這麼複雜!你就不能寫簡單點嗎?

那我解釋下,如果出現兩個及以上連續字元,那麼後一個的次序一定是前一個的次序+1,如果這個【聯絡】斷掉之後,就證明連續的部分已經結束,需要重新開始判斷是否連續了。 lastloc 用來記錄【可能】連續的字串的首位次序,然後放進一個字典中,如果後一個次序剛好是前一個次序+1,那麼對應的【重複次數】就要增加1

(肯定有十分簡單的方法,但我只能想到這種)

好了,現在已經得到不存在的字元在給定字串中的起始位置和長度,接下來進行歸類。

思路是,對上一步得到的位置長度列表每迴圈一次,就把鍵之前的字串取出來放到一邊,把鍵和它對應長度的字串取出來放到另一邊。

這樣迴圈結束後,如果還剩下字串沒處理,那這段字串一定就是由指定字符集中沒有出現過的字元組成的。

這樣就全部劃分完了。

具體實現:

       index = 0;
       lastloc = 0;
       foreach (var key in loctemp.Keys)
       {
           if (key > lastloc)//其實這裡的判斷只需要在開頭第一遍迴圈中加入,對應的是字串開頭就匹配到了的情況
           {
               result.Add(new Sentence()
               {
                  Order = index,
                  Data = input.Substring(lastloc, key - lastloc),
                  Failed = false
               });
               index++;
           }

           result.Add(new Sentence()
           {
               Order = index, 
               Data = input.Substring(key, loctemp[key]),
               Failed = true
           });
           lastloc = key + loctemp[key];
           index++;
       }
       if (lastloc < input.Length)
       {
           result.Add(new Sentence()
           {
               Order = index,
               Data = input.Substring(lastloc),
               Failed = false
           });
       }

這樣整個就做完了。

當然這樣的需求我估計應該沒人會碰到,而且在我寫的工具裡都封裝過了,就不貼出完整程式碼了。

測試結果(不要在意細節)(不要在意內容)(不要在意指定的字符集)(啥都不要在意):