Posted on 2011-10-15 08:00
S.l.e!ep.¢% 閱讀(806)
評論(0) 編輯 收藏 引用 所屬分類:
C++
前段時(shí)間整理臺(tái)歷的邏輯數(shù)據(jù)時(shí)考慮到需要去兼容已發(fā)布的照片書數(shù)據(jù),很多地方做了兼容處理,比如下面這個(gè)例子:
????? 在很多時(shí)候,我們常常會(huì)使用map儲(chǔ)存一些需要經(jīng)常查詢數(shù)據(jù)結(jié)構(gòu),而map的key在一開始設(shè)計(jì)的時(shí)候往往不多加思索,很容易就認(rèn)為它就是個(gè)純ID,比如一個(gè)數(shù)字,或者一個(gè)字符串。當(dāng)隨著產(chǎn)品變得復(fù)雜,或者不同數(shù)據(jù)結(jié)構(gòu)的添加,這個(gè)假設(shè)往往不堪一擊—-比如在網(wǎng)游中的游戲ID竟然被認(rèn)為是唯一的Key,而實(shí)際上如果涉及到服務(wù)器合并,這個(gè)ID也就不那么唯一了。很顯然需要解決這個(gè)問題就是擴(kuò)充原來的Key:要么還是將附加信息直接和原先的Key合并,要么將它倆合并到一個(gè)數(shù)據(jù)結(jié)構(gòu)中—-而后者會(huì)引來一個(gè)小問題:
?????? 如果我把這個(gè)Key儲(chǔ)存在某個(gè)有序容器中,我就需要重新告訴他各個(gè)key是按照什么順序排序的。
????? 在做照片書的時(shí)候,服務(wù)器告訴你:哦,我們的模板ID就是唯一標(biāo)識(shí)了,你拿這個(gè)ID就可以得到我這邊關(guān)于這個(gè)作品的所有數(shù)據(jù)。而到了做臺(tái)歷的時(shí)候,服務(wù)器換了種說法:不好意思,為了充分利用資源,我們很多臺(tái)歷用得是同一個(gè)模板,你還要告訴我這個(gè)臺(tái)歷的產(chǎn)品ID。于是shit就這么發(fā)生了。
?????? 可憐的Key就從string templateID,變成了struct TemplateKey{string m_sTemplateID;string m_sProductID};嗯,這不是什么問題,比較煩的就是如果你用map來儲(chǔ)存,那你就得自己重寫排序比較函數(shù),于是你有了如下的代碼:
1 | booloperator<(constTemplateSearchKey &searchKey) const |
3 | ????????returnm_sProductID < searchKey.m_sProductID && |
4 | ???????????????m_sTemplateID < searchKey.m_sTemplateID; |
可惜的是這樣的代碼大錯(cuò)特錯(cuò),試試下面的代碼
07 | structTemplateSearchKey |
09 | ????string m_sProductID; |
10 | ????string m_sTemplateID; |
11 | ????TemplateSearchKey(conststring& sTemplateID,conststring& sProductID) |
13 | ????????m_sTemplateID??? = sTemplateID; |
14 | ????????m_sProductID??? = sProductID; |
17 | ????booloperator<(constTemplateSearchKey &searchKey) const |
19 | ????????returnm_sProductID < searchKey.m_sProductID && |
20 | ???????????????m_sTemplateID < searchKey.m_sTemplateID; |
26 | ????map<TemplateSearchKey,string> testMap; |
27 | ????TemplateSearchKey key("","2"); |
28 | ????TemplateSearchKey key1("","1"); |
29 | ????TemplateSearchKey key2("","3"); |
30 | ????testMap[key] = "a"; |
31 | ????testMap[key1] = "b"; |
32 | ????testMap[key2] = "c"; |
33 | ????cout<<testMap[key]<<endl; |
做調(diào)整:
1 | booloperator<(constTemplateSearchKey &searchKey) const |
4 | ???????returnm_sProductID < searchKey.m_sProductID || |
5 | ??????????????m_sTemplateID < searchKey.m_sTemplateID; |
?
而這個(gè)連編譯都是不通過的……出一個(gè)ASSERT告訴你你的<符號(hào)是無效的。
01 | template<class_Pr, class_Ty1, class_Ty2> inline |
02 | bool__CLRCALL_OR_CDECL _Debug_lt_pred(_Pr _Pred, const_Ty1& _Left, const_Ty2& _Right, |
04 | ????constwchar_t*_Where, unsigned int_Line) |
08 | if(!_Pred(_Left, _Right)) |
12 | elseif(_Pred(_Right, _Left)) |
14 | ????_DEBUG_ERROR2("invalid operator<", _Where, _Line); |
于是趕緊琢磨了下,改了:
01 | booloperator<(constTemplateSearchKey &searchKey) const |
04 | ????if(m_sProductID == searchKey.m_sProductID) |
06 | ????????returnm_sTemplateID < searchKey.m_sTemplateID; |
10 | ????????returnm_sProductID < searchKey.m_sProductID; |
OK,編譯通過,運(yùn)行沒問題。可問題也來了,如果有3個(gè)成員呢?4個(gè)5個(gè)呢?一個(gè)比較好的方法就是直接把每個(gè)成員hash成一個(gè)數(shù)值,然后各個(gè)數(shù)值鏈起來,通過比較最后這個(gè)值來確定大小。于是就想了,為啥不學(xué)JAVA直接把排序功能切成兩部分—-兩個(gè)函數(shù)hasCode和equals,一個(gè)用來確定東西怎么排序,而另外一個(gè)用來確定是不是同一個(gè)東西。而STL這種做法雖然簡練卻晦澀,需要用戶自己去考慮我寫完的排序函數(shù)是不是符合傳說中的排序三定律(有時(shí)候即使符合也不能完全反應(yīng)用戶原意)。