2016-04-22 8 views
9

मैं इस तरह के कई hardcoded सत्यापन:'पूर्णांक के सेट' के लिए क्या डेल्फी प्रकार है?

const 
    cLstAct  = 1; 
    cLstOrg  = 4; 
    cLstClockAct = 11; 
const 
    FUNCT_1 = 224; 
    FUNCT_2 = 127; 
    FUNCT_3 = 3; 

if lFuncID in [FUNCT_1,FUNCT_2,FUNCT_3] then ... 
if not (lListType in [cLstAct..cLstOrg,cLstClockAct]) then ... 
if not (lPurpose in [0..2]) then ... 

कि मैं

function ValidateInSet(AIntValue: integer; AIntSet: @@@): Boolean; 
begin 
    Result := (AIntValue in AIntSet); 
    if not Result then ... 
end; 

लेकिन किस प्रकार AIntSet के लिए चयन करने के लिए की तरह एक आम विधि के साथ बदलना चाहते हैं?

वर्तमान में कोड के दौरान परीक्षण किए जाने वाले मानों को एक कॉन्स वैल्यू 232 तक जाना जाता है (इसलिए मैं एक टीबीटीएससेट = बाइट का सेट का उपयोग कर सकता हूं), लेकिन मैं भविष्यवाणी कर सकता हूं कि हम E1012 Constant expression violates subrange bounds में स्थिर हो जाएंगे जब निरंतर मान अधिक हो जाएंगे 255

मेरा गूगल फू मुझे यहाँ विफल रहता है ...

(डेल्फी सिएटल अद्यतन 1 पर वर्तमान में)

+1

Spring4D एक THashSet है: http://www.devjetsoftware.com/docs/spring4d/index.htm?Spring .Collections.Sets.THashSet% 28T% 29.IsSupersetOf.htm – Johan

+0

मजेदार है कि एफपीसी में AFAIR एक बड़े सेट के रूप में बना सकता है क्योंकि स्मृति में प्रबंधन होता है। हालांकि मुझे यकीन नहीं है कि यह विशिष्ट डेल्फी सीमा वास्तव में एक लाभ नहीं है ... –

+0

आप जेनेरिक सेट [यहां] (http://stackoverflow.com/a/19524788/576719) का उपयोग कर सकते हैं। –

उत्तर

4

आप उपयोग कर सकते हैं एक array of Integer:

function ValidateInSet(AIntValue: integer; AIntSet: array of Integer): Boolean; 
var 
    I: Integer; 
begin 
    Result := False; 
    for I := Low(AIntSet) to High(AIntSet) do 
    begin 
    if AIntSet[I] = AIntValue then 
    begin 
     Result := True; 
     Break; 
    end; 
    end; 
    if not Result then ... 
end; 

const 
    cLstAct  = 1; 
    cLstOrg  = 4; 
    cLstClockAct = 11; 
const 
    FUNCT_1 = 224; 
    FUNCT_2 = 127; 
    FUNCT_3 = 3; 

if ValidateInSet(lFuncID, [FUNCT_1, FUNCT_2, FUNCT_3]) then ... 
if not ValidateInSet(lListType, [cLstAct, 2, 3, cLstOrg, cLstClockAct]) then ... 
if not ValidateInSet(lPurpose, [0, 1, 2]) then ... 
+0

मैं इस समाधान के लिए जा रहा हूं क्योंकि यह मेरे मौजूदा कोड के साथ फिट बैठता है; संरचनाओं को पहले से परिभाषित करने और भरने की कोई ज़रूरत नहीं है (जैसे मुझे लगता है कि अगर मैं एक टीबीई का उपयोग करता हूं)। केवल एक चीज जो मुझे बदलनी थी, उदा। 'यदि वैध नहीं है (lururpose, [0..2],' उद्देश्य ', झूठा) 'to' मान्य नहीं है अगर वैध नहीं है (lururpose, [0,1,2],' उद्देश्य ', झूठा) ' –

8

उपयोग एक शब्दकोश, TDictionary<Integer, Integer>। मान अप्रासंगिक है और आप केवल कुंजी के बारे में परवाह करते हैं। यदि शब्दकोश में एक विशिष्ट कुंजी होती है तो वह कुंजी सेट का सदस्य होता है। सदस्यता का परीक्षण करने के लिए सदस्य और ContainsKey को हटाने के लिए सदस्य, Remove सदस्य जोड़ने के लिए AddOrSetValue का उपयोग करें।

एक शब्दकोश का उपयोग करने का बिंदु यह है कि यह आपको ओ (1) लुकअप देता है।

आप इस प्रकार को सीधे सेट के रूप में उपयोग नहीं करना चाहते हैं। आपको इसे उस वर्ग में लपेटना चाहिए जो केवल क्षमताओं की तरह सेट का खुलासा करता है। इसका एक उदाहरण यहां पाया जा सकता है: https://stackoverflow.com/a/33530037/505088

+1

'TDictionary ' बेहतर होगा –

+0

@arioch वास्तव में –

+0

क्यों नहीं? उन पूर्णांकों के लिए जो पंजीकृत होंगे जो पदचिह्न को कम करना चाहिए। –

1

यदि आप हाल ही में डेल्फी संस्करण पर हैं, तो आप TArray<Integer> का उपयोग कर सकते हैं।

if ValidateInSet(lFuncID, [FUNCT_1,FUNCT_2,FUNCT_3]) then begin 

    end; 
+2

कोई फर्क नहीं पड़ता कि मैं दृढ़ता से तर्क दूंगा कि ओ (1) पहुंच महत्वपूर्ण है और चूंकि इसे हासिल करना इतना आसान है, यह ओ (एन) पहुंच के लिए गरीब लगता है। –

+0

यह कोशिश की, लेकिन काम नहीं करता है: आपके उदाहरण कथन पर असंगत प्रकार, 'ValidateInSet (lListType, [cLstAct..cLstOrg, cLstClockAct]) जैसी चीजों का उल्लेख न करें) –

+0

बजाय कमजोर डिज़ाइन के कारण सरणी और सेट के बीच सिंटैक्टिकल भ्रम के बहुत सारे सरणी अक्षर का। –

1

सीधा जवाब TBits वर्ग

http://docwiki.embarcadero.com/Libraries/Seattle/en/System.Classes.TBits.Bits

नोट होगा::

function ValidateInSet(AIntValue: integer; const AIntSet: TArray<Integer>): Boolean; 
var 
    N: Integer; 
begin 
    { option1 : if AIntSet is always sorted } 
    result := TArray.BinarySearch(AIntSet, AIntValue, N); 

    { option 2: works for any array } 
    result := false; 
    for N in AIntSet do begin 
    if AIntValue = N then begin 
     result := true; 
     Break; 
    end; 
    end; 

    if not Result then begin 
    // ... 
    end; 
end; 

कॉलिंग केवल एक सेट (श्रेणियों के लिए छोड़कर) के साथ के रूप में ही है यह केवल डेल्फी XE4 के साथ शुरू किया जा सकता है - http://qc.embarcadero.com/wc/qcmain.aspx?d=108829

हालांकि के लिए

अपने सबसे फुलाया मामले में "पूर्णांकों का सेट" यह स्मृति के 2^31/8 बाइट्स ले जाएगा (क्योंकि पूर्णांक के नकारात्मक मान भी विचार नहीं किया जाएगा), और कहा कि एक बहुत होगा ... तो मैं आशा है कि आप कभी भी पूर्ण पूर्णांक का सेट नहीं करना चाहेंगे। या आपको इसके बजाय स्पैर्स Arrays में निवेश करना चाहिए।

function ValidateInSet(const AIntValue: integer; const AIntSet: TBits): Boolean; 
begin 
    Result := (AIntValue >= 0) and (AIntValue < AIntSet.Size); 
    if Result then 
    Result := AIntSet.Bits[AIntValue]; 
    if not Result then ... 
    v-a-l-i-d-a-t-e 
end; 

या बल्कि

function ValidateInSet(const AIntValue: integer; const AIntSet: TBits): Boolean; 
begin 
    Result := false; 

    if AIntValue < 0 then exit;    // Validation criterion #1 
    if AIntValue >= AIntSet.Size then exit; // Validation criterion #2 
    if not AIntSet.Bits[AIntValue] then exit; // Validation criterion #3 

    if .... then exit;      // Validation criterion #4 
    if .... then exit;      // Validation criterion #5 
    if .... then exit;      // Validation criterion #6 

    Result := true; 
end; 

या शायद

TSetTestCriterion = TFunc<Integer, Boolean>; 
TSetTestCriteria = TArray<TFunc<Integer, Boolean>>; 

function ValidateInSet(const AIntValue: integer; 
    const AIntSet: TBits; const Tests: TSetTestCriteria = nil): Boolean; 
var ExtraTest: TSetTestCriterion; 
begin 
    Result := false; 

    if AIntValue < 0 then exit;    // Validation criterion #1 
    if AIntValue >= AIntSet.Size then exit; // Validation criterion #2 
    if not AIntSet.Bits[AIntValue] then exit; // Validation criterion #3 

    if Tests <> nil then   // Validation criteria #4, #5, #6, ... 
    for ExtraTest in Tests do 
     if not ExtraTest(AIntValue) then exit;   

    Result := true; 
end; 

http://docwiki.embarcadero.com/Libraries/Seattle/en/System.SysUtils.TFunc

अब - बस डेमो के लिए, वास्तविक अनुप्रयोग में आप उन की स्थापना की और सरणी एक बार और कैश के लिए पैदा करेगा लंबे (हमेशा के लिए, या कम से कम जब तक कि कॉन्फ़िगरेशन परिवर्तन उन्हें पुनर्निर्माण की मांग नहीं करेगा)।

Type FuncIDs = (FUNCT_3 = 3, FUNCT_2 = 127, FUNCT_1 = 224); 

var MysticGlobalFlag: Boolean; 

function ValidateFuncID(const lFuncID: FuncIDs): Boolean; 
var map: TBits; 
begin 
    map := TBits.Create; 
    try 
    map.Size := High(lFuncID) + 1; 
    map.Bits[ Ord(Func_1) ] := True; 
    map.Bits[ Ord(Func_2) ] := True; 
    map.Bits[ Ord(Func_3) ] := True; 

    Result := ValidateInSet(Ord(lFuncID), map, 
     TSetTestCriteria.Create(
      function(lFuncID: integer) : Boolean 
      begin 
      Result := MysticGlobalFlag or (lFuncID <> Ord(FuncIDs.FUNC_2)) 
      end 
     , 
      function(lFuncID: integer) : Boolean 
      begin 
      Result := (lFuncID <> Ord(FuncIDs.FUNC_3)) or (DayOfTheWeek(Now()) = 4) 
      end 
     ) 
    ); 
    finally 
    map.Destroy; 
    end; 

    if not Result then // from the original question code 
    ...    // seems like a placeholder for error handling or object creation and registration 
end; 
+1

मुझे समझ में नहीं आता कि आपके फ़ंक्शन यह जांचने के लिए क्यों करते हैं कि एक सेट में कोई मान कितना जटिल है या नहीं। –

+0

क्योंकि विषय स्टार्टर ने असफल खोज के बाद विशेष प्रसंस्करण जोड़ा। वैसे भी, अतिरिक्त परीक्षणों को हटाने एक हवा है। हालांकि टीएस चाहता था कि एक ही फ़ंक्शन अलग-अलग डोमेन के साथ काम करे और फिर –

+1

रखने के लिए एक्स्टेंसिबिलिटी अच्छी बात है नोट करें कि [QualityCentral अब बंद हो गया है] (https://community.embarcadero.com/blogs/entry/quality-keeps-moving फॉरवर्ड), इसलिए आप अब 'qc.embarcadero.com' लिंक तक नहीं पहुंच सकते हैं। यदि आपको पुराने क्यूसी डेटा तक पहुंच की आवश्यकता है, तो [QCScraper] (http://www.uweraabe.de/Blog/2017/06/09/how-to-save-qualitycentral/) देखें। –

संबंधित मुद्दे