2010-02-01 11 views
13

में अलग-अलग क्रमबद्ध करने के लिए TStringList कैसे प्राप्त कर सकता हूं मेरे पास एक साधारण TStringList है। मैं उस पर एक TStringList.Sort करता हूँ।मैं डेल्फी

फिर मैंने देखा कि अंडरस्कोर "_" पूंजी पत्र "ए" से पहले है। यह एक तीसरे पक्ष के पैकेज के विपरीत था जो एक ही पाठ को सॉर्ट कर रहा था और ए

एएनएसआई चरित्र सेट के अनुसार, एजेड वर्ण 65 - 9 0 और _ 9 5 है। तो यह तीसरी पार्टी की तरह दिखता है पैकेज उस ऑर्डर का उपयोग कर रहा है और TStringList.Sort नहीं है।

मैं TStringList.Sort के गले में डूब गया और यह AnsiCompareStr (केस संवेदनशील) या AnsiCompareText (केस असंवेदनशील) का उपयोग कर सॉर्ट कर रहा है। मैंने इसे दोनों तरीकों से आजमाया, मेरी स्ट्रिंगलिस्ट के केस संवेदनशील मूल्य को सत्य और फिर गलत पर सेट किया। लेकिन दोनों मामलों में, "_" पहले टाइप करता है।

मैं कल्पना नहीं कर सकता कि यह TStringList में एक बग है। तो यहां कुछ और होना चाहिए जो मैं नहीं देख रहा हूं। वह क्या हो सकता है?

मुझे वास्तव में यह जानने की ज़रूरत है कि मैं अपने TStringList को सॉर्ट करने के लिए कैसे प्राप्त कर सकता हूं ताकि यह अन्य पैकेज के समान क्रम में हो।

संदर्भ के लिए, मैं डेल्फी 200 का उपयोग कर रहा हूं और मैं अपने कार्यक्रम में यूनिकोड स्ट्रिंग का उपयोग कर रहा हूं।

type 
    TMyStringList = class(TStringList) 
    protected 
    function CompareStrings(const S1, S2: string): Integer; override; 
    end; 

function TMyStringList.CompareStrings(const S1, S2: string): Integer; 
begin 
    if CaseSensitive then 
    Result := CompareStr(S1, S2) 
    else 
    Result := CompareText(S1, S2); 
end; 
+3

विंडोज 'ए' से पहले' _' भी टाइप करता है, इसलिए टीस्ट्रिंगलिस्ट कम से कम ओएस के साथ मिलती है। –

+2

परिणाम प्राप्त करने की उम्मीद नहीं है, इसका मतलब यह नहीं है कि यह एक बग है। यह एक बग नहीं है, इसे क्रमबद्ध करने के क्रम में उपयोगकर्ता के (या ओएस की उपयोगकर्ता की तरफ से) का सही ढंग से समर्थन करने के लिए इस तरह से डिज़ाइन किया गया है। –

+0

आप इस प्रश्न को इस धारणा के साथ लिख रहे हैं कि * * * nonalphabetic वर्णों को क्रमबद्ध करने का एक सही तरीका है। अंडरस्कोर शब्द आपके शब्दकोश में कहां दिखाई देते हैं? –

उत्तर

35

परिभाषित करने के लिए " सही ढंग से "।
i18n सॉर्टिंग पूरी तरह से आपके लोकेल पर निर्भर करता है।
तो मैं पूरी तरह से PA से सहमत हूं कि यह एक बग नहीं है: डिफ़ॉल्ट सॉर्ट करें व्यवहार कार्य करता है जो i18n को ठीक से काम करने की अनुमति देने के लिए डिज़ाइन किया गया है।

तरह Gerry का उल्लेख है, TStringList.Sort का उपयोग करता AnsiCompareStr और AnsiCompareText (मैं कुछ पंक्तियां यह कैसे करता है में यह बताएँगे)।

लेकिन: TStringList लचीला है, यह क्रमबद्ध, CustomSort और CompareStrings है, जो सभी आभासी हैं इसके अलावा (ताकि आप उन्हें एक वंशज कक्षा में ओवरराइड कर सकते हैं)
होता है, जब आप CustomSort कहते हैं, आप अपने में प्लग कर सकते हैं फ़ंक्शन की तुलना करें।

इस उत्तर के कम से एक समारोह की तुलना करता है कि आप क्या चाहते है:

  • केस संवेदनशील
  • नहीं
  • किसी भी स्थान का उपयोग कर
  • बस तार के पात्रों में से क्रमसूचक मूल्य की तुलना

CustomSort इस रूप में परिभाषित किया गया है:

procedure TStringList.CustomSort(Compare: TStringListSortCompare); 
begin 
    if not Sorted and (FCount > 1) then 
    begin 
    Changing; 
    QuickSort(0, FCount - 1, Compare); 
    Changed; 
    end; 
end; 

डिफ़ॉल्ट रूप से, क्रमबद्ध विधि एक बहुत ही सरल कार्यान्वयन है, एक डिफ़ॉल्ट समारोह कहा जाता StringListCompareStrings तुलना गुजर:

procedure TStringList.Sort; 
begin 
    CustomSort(StringListCompareStrings); 
end; 

तो, अगर आप अपने खुद के TStringListSortCompare को परिभाषित संगत विधि की तुलना करें, तो आप अपनी खुद की सॉर्टिंग को परिभाषित कर सकते हैं।

type 
    TStringListSortCompare = function(List: TStringList; Index1, Index2: Integer): Integer; 

आप StringListCompareStrings एक दिशानिर्देश के रूप में अपने को लागू करने के लिए उपयोग कर सकते हैं:

function StringListCompareStrings(List: TStringList; Index1, Index2: Integer): Integer; 
begin 
    Result := List.CompareStrings(List.FList^[Index1].FString, 
           List.FList^[Index2].FString); 
end; 

TStringListSortCompare एक वैश्विक समारोह आइटम आप तुलना करना चाहते चर्चा करते हुए TStringList और इंडेक्स लेने के रूप में परिभाषित किया गया है

तो, डिफ़ॉल्ट रूप से TStringList.Sort TList.CompareStrings को defers:

function TStringList.CompareStrings(const S1, S2: string): Integer; 
begin 
    if CaseSensitive then 
    Result := AnsiCompareStr(S1, S2) 
    else 
    Result := AnsiCompareText(S1, S2); 
end; 

कौन सा तो नीचे झूठ बोल रही है Windows API समारोह CompareString डिफ़ॉल्ट उपयोगकर्ता का स्थान LOCALE_USER_DEFAULT साथ उपयोग करें:

function AnsiCompareStr(const S1, S2: string): Integer; 
begin 
    Result := CompareString(LOCALE_USER_DEFAULT, 0, PChar(S1), Length(S1), 
    PChar(S2), Length(S2)) - 2; 
end; 

function AnsiCompareText(const S1, S2: string): Integer; 
begin 
    Result := CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, PChar(S1), 
    Length(S1), PChar(S2), Length(S2)) - 2; 
end; 

अंत में समारोह आप की जरूरत की तुलना करें। फिर सीमाएं:

  • केस संवेदनशील
  • किसी भी स्थान का उपयोग नहीं
  • बस तार

के पात्रों की क्रमसूचक मूल्य की तुलना इस कोड है:

function StringListCompareStringsByOrdinalCharacterValue(List: TStringList; Index1, Index2: Integer): Integer; 
var 
    First: string; 
    Second: string; 
begin 
    First := List[Index1]; 
    Second := List[Index2]; 
    if List.CaseSensitive then 
    Result := CompareStr(First, Second) 
    else 
    Result := CompareText(First, Second); 
end; 

डेल्फी बंद नहीं है, काफी विपरीत: अक्सर यह वास्तव में एक लचीला वास्तुकला है।
अक्सर यह देखने के लिए खुदाई होती है कि आप उस लचीलेपन में कहां लगा सकते हैं।

E1 E1 e2 E2

सही क्रम है (उदाहरण के लिए: क्योंकि यह वर्ण punctation साथ बराबर के रूप में हो जाता है

--jeroen

+0

बहुत अच्छा! मैं इसके बारे में जानता था, लेकिन यह सब पहले एक ही स्थान पर वर्णित नहीं देखा था। –

+0

यही कारण है कि मैंने इसे एक समुदाय विकी बना दिया :-) –

5

AnsiCompareStr/AnsiCompareText खाते में चरित्र संख्या से अधिक ले:


तो अंतिम जवाब यहाँ ओवरराइड करने के लिए Ansi आप जो कुछ भी चाहता हूँ के साथ तुलना (जैसे गैर एएनएसआई तुलना) इस प्रकार है। वे ले उपयोगकर्ताओं को ध्यान में स्थान में है, इसलिए "ई" "é" के साथ क्रमित कर देगा, 'ई' आदि

यह Ascii क्रम में यह सॉर्ट, एक कस्टम का उपयोग तुलना समारोह as described here

0

AnsiCompareStr (LOCALE_USER_DEFAULT साथ CompareString), गलती है चेक के लिए):

ई 1 ई 2 é1 é2

क्या कोई यह जानता है कि आदेश में इस त्रुटि से कैसे बचें?


11.2.2010: मुझे माफी माँगनी चाहिए व्यवहार भाषा पूरी तरह से भाषाई नियमों के अनुसार है। हालांकि मुझे लगता है कि यह मूर्खतापूर्ण और "खराब" है, यह एपीआई फ़ंक्शन में त्रुटि नहीं है।

विंडोज एक्सपी में एक्सप्लोरर तथाकथित अंतर्ज्ञानी फ़ाइल नाम ऑर्डरिंग का उपयोग करता है जो बेहतर परिणाम देता है लेकिन इसे प्रोग्रामिक रूप से उपयोग नहीं किया जा सकता है।