2014-02-27 52 views
1

I字符串格式爲name:key:dataLength:data,這些字符串通常可以鏈接在一起。例如"aNum:n:4:9879aBool:b:1:taString:s:2:Hi"這將映射到一個對象是這樣的:飛鏢高效的字符串處理技術?

{ 
    aNum: 9879, 
    aBool: true, 
    aString: "Hi" 
} 

我解析這個格式的字符串的方法,但我不知道它是否是使用substring被pprocessing字符串的最有效的方法,有沒有處理字符串以這種方式更有效的方式(重複斬去前部):

Map<string, dynamic> fromString(String s){ 
    Map<String, dynamic> _internal = new Map(); 
    int start = 0; 
    while(start < s.length){ 
    int end; 
    List<String> parts = new List<String>(); //0 is name, 1 is key, 2 is data length, 3 is data 
    for(var i = 0; i < 4; i++){ 
     end = i < 3 ? s.indexOf(':') : num.parse(parts[2]); 
     parts[i] = s.substring(start, end); 
     start = i < 3 ? end + 1 : end; 
    } 
    var tranType = _tranTypesByKey[parts[1]]; //this is just a map to an object which has a function that can convert the data section of the string into an object 
    _internal[parts[0]] = tranType._fromStr(parts[3]); 
    } 
    return _internal; 
} 
+0

您能否提供有關此類字符串的預期大小或您想要一次處理多少個這樣的字符串的信息。它取決於很多這樣的信息,哪些策略是有意義的,或者如果投入時間進行優化是有意義的。 –

+0

字符串的數據部分在大小和內容方面可以是絕對的任何東西,並且這些對象的鏈接也可能是巨大的,我不希望它們成爲我個人使用它們的唯一原因將只使用小型簡單對象,但是類應該支持具有任意數量屬性的對象。 – 0xor1

+0

然後,您也可以考慮使用流進行異步處理,並使用[有限狀態機](http://en.wikipedia.org/wiki/Finite-state_machine)進行解析,因此您不需要更多而不是同時在內存中的一個副本。當數據仍在接收時,您也可能已經開始處理數據。對於小塊可能比較慢,但對於大量數據可能會更快。 –

回答

1

我會嘗試s.split(':')和處理結果列表。 如果你做了很多這樣的操作,你應該考慮創建基準測試,嘗試不同的技術並進行比較。

如果您仍然需要這條線

s = i < 3 ? s.substring(idx + 1) : s.substring(idx); 

我會避免產生在每個迭代一個新的子而只是跟蹤next位置。

+0

我沒有去的唯一原因'split(':')'是因爲我不能保證字符串的數據部分不會有':',所以我最終還是希望將這些位重新加入備份。追蹤下一個位置,而不是重複覆蓋原始字符串。 – 0xor1

+0

我明白了。然後定界符是':x:y:',其中'x'是一些類型信息,'y'是字段標識符。你可以嘗試這個正則表達式。我聽說Dart正則表達式還不是很快,但我會考慮並測試它。 –

1

您必須決定性能與代碼的可讀性和可維護性之間的關係。

也就是說,你不應該反覆切斷字符串的頭部。這是保證效率低下的 - 它會花費你的字符串記錄數量的二次方,只是創建這些尾部字符串。

對於解析每個字段,您可以避免在長度和類型字段上執行子字符串。對於長度字段,你可以建立自己的號:

int index = ...; 
// index points to first digit of length. 
int length = 0; 
int charCode = source.codeUnitAt(index++); 
while (charCode != CHAR_COLON) { 
    length = 10 * length + charCode - 0x30; 
    charCode = source.codeUnitAt(index++); 
} 
// index points to the first character of content. 

由於長度通常是小整數(小於2 < < 31),這很可能是比創建一個字符串並調用int.parse更高效。

類型字段是一個ASCII字符,所以你可以使用codeUnitAt以獲得其ASCII值,而不是建立一個單一字符的字符串(然後你的內容解釋查找需要的字符代碼,而不是字符串轉換) 。

對於解析內容,您可以傳遞源字符串,開始索引和長度,而不是創建子字符串。然後,布爾分析器也可以讀取代碼單元而不是單字符字符串,字符串分析器可以創建子字符串,而數字解析器也可能必須創建一個子字符串,然後調用double.parse。

如果Dart有一個double.parseSubstring(source,[int from = 0,int to]),可以將子字符串解析爲double而不創建子字符串,這將會很方便。

+0

感謝這只是我正在尋找的另類想法 – 0xor1