टीएलिस्ट से हटाएं (0) में टीएलिस्ट की शुरुआत से आइटमों का एक बड़ा ब्लॉक हटाने का एक प्रभावी तरीका महंगा है क्योंकि सभी बाद के आइटमों को स्थानांतरित करने की आवश्यकता है। अगर मुझे एक बड़ी सूची की शुरुआत से बड़ी संख्या में आइटम हटाना होगा तो सबसे तेज़ तरीका क्या है?डेल्फी
डेल्फी
उत्तर
TList
की शुरुआत से तत्वों की एक बड़ी श्रृंखला को हटाना महंगा है। यद्यपि कक्षा का नाम धोखा देने के लिए flatters, TList
वास्तव में एक सरणी है। TList
में कोई सीमा हटाने की कोई सुविधा नहीं है- प्रत्येक आइटम को व्यक्तिगत रूप से हटा दिया जाना चाहिए और फिर बाकी की सूची नीचे ले जाया गया है। एक बड़ी श्रृंखला के लिए जो एक बहुत सारे पुनर्विक्रय और पूर्ण सूची चाल को उकसाएगा।
यदि आपके पास अधिक आधुनिक डेल्फी था तो आप सामान्य सूची वर्ग TList<T>
का उपयोग कर सकते हैं और DeleteRange
विधि का लाभ उठा सकते हैं। दस्तावेज़ीकरण में यह महत्वपूर्ण नोट शामिल है:
यह एक ओ (ACount) ऑपरेशन है।
डेल्फी 2006 में आप इस तरह बराबर प्रदर्शन विशेषताओं के साथ कुछ लिख सकते हैं:
procedure DeleteRange(List: TList; AIndex, ACount: Integer);
var
i: Integer;
NewCount: Integer;
begin
NewCount := List.Count-ACount;
Assert(AIndex>=0);
Assert(ACount>=0);
Assert(NewCount>=0);
for i := AIndex to NewCount-1 do
List[i] := List[i+ACount]
List.Count := NewCount;
end;
+1। अच्छा जवाब, और डी 2006 समकक्ष के साथ अच्छा जोड़ा। –
इतना अच्छा नहीं है। अनुमान लगाएं [TList.Count] (http://docwiki.embarcadero.com/VCL/en/Classes.TList.Count) संपत्ति सेटटर करते हैं। यह आंतरिक रूप से [TList.Delete] (http://docwiki.embarcadero.com/VCL/en/Classes.TList.Delete) को पुराने मान से नए मान में पुनरावृत्ति में कॉल करता है। तो कोई प्रदर्शन वृद्धि नहीं है। और, डेविड, [TList.Notify] के बारे में नोट (http://docwiki.embarcadero.com/VCL/en/Classes.TList.Notify), आप आंतरिक [TList.Delete] के बाद भी इसे प्राप्त करेंगे (http: //docwiki.embarcadero.com/VCL/en/Classes.TList.Delete) कॉल करता है। – TLama
@TLama मेरे डेल्फी के पास एक कुशल सेटकाउंट है। आप किस संस्करण को देख रहे हैं? वही है, अंत में हटाना सस्ता है जब क्षमता नहीं बदली जाती है। स्पष्ट होने के लिए, हटाएं (गणना -1) हटाएं (0) से पूरी तरह से अलग है। –
सबसे पहले, प्रत्येक आइटम को हटाकर टीएलआईस्ट के यूआई को अपडेट करने से रोकने के लिए BeginUpdate और EndUpdate का उपयोग करें।
दूसरा: सबसे पहले सूची में सबसे कम आइटम को हटाने का प्रयास करें। दूसरे शब्दों में, सूची से ऊपर तक की वस्तुओं को हटाने से अन्य वस्तुओं पर कम कुशलता मिलती है। ,
for I := 0 to List.Count - N - 1 do
list[I] := list[I + N];
for I := list.Count - 1 downto list.Count - N do
list.Delete(I)
मैं बहुत अच्छी तरह से के माध्यम से इस कोड में नहीं सोचा तो आप बंद-एक करके जांच करने के लिए की आवश्यकता होगी:
TList पर कोई 'BeginUpdate' या' EndUpdate' नहीं है। –
कोई भी "टीएलआईस्ट का यूआई" नहीं है; 'TList' एक ग्राफिक घटक नहीं है। और मुझे पूरा यकीन नहीं है कि दूसरा अनुच्छेद क्या कहता है - क्या आप अपना उत्तर संपादित कर सकते हैं? –
तो आदेश मामलों, और आप मोर्चे पर दूर करने के लिए एन आइटम नहीं हैं त्रुटियों और पसंद है।
यदि ऑर्डर कोई फर्क नहीं पड़ता है, तो आप पहले एन आइटम को पहले एन आइटम के साथ एक्सचेंज कर सकते हैं और उपरोक्त अंतिम एन आइटम को हटा सकते हैं।
हटाने का आदेश कोई फर्क नहीं पड़ता। क्या आप एक टीएलआईस्ट के लिए "सेट लम्बाई" कर सकते हैं? - यह हटाएं एन बार कॉल करने से तेज़ होगा। – rossmcm
@ross हाँ आप कर सकते हैं। आप बस 'List.Count: = ...' –
+1 यह एक अच्छा जवाब है, लेकिन इसे सूची के उपयोग के साथ शीर्ष पर रखा जाएगा। काउंटर –
मार्सेलो जैसा कि पहले ही कहा, आप के बजाय आइटम करके उस आइटम कर के पूरे ब्लॉक नीचे नकल कर सकता है, लेकिन, आप तर्क के रूप में TList.List
का उपयोग करके, एक कॉल को मूव() में ले जाया जा सकता है।
ध्यान दें कि TList.List
था एक PPointerList
(^TPointerList; TPointerList = array[0..MaxListSize - 1] of Pointer;
) पुराने डेल्फी संस्करणों में और बन गया एक TPointerList
(TPointerList = array of Pointer;
) डेल्फी XE2 में है, तो आप सही अविवेक का उपयोग करना चाहिए:
TList(aList).List^[index] // for older Delphi's
और
TList(aList).List[index] // for Delphi XE2
वह 'TList.Notify' को विचलित कर देगा, लेकिन इससे कोई फर्क नहीं पड़ता –
अभी भी, यह अतिरिक्त जटिलता को न्यायसंगत बनाने के लिए पर्याप्त तेज़ हो सकता है। – afrazier
यहां आप XE2 में ऐसा कैसे करते हैं, क्योंकि टीएलिस्ट पॉइंटर्स की एक सरणी है।
कार्यान्वयन डेल्फी 2006 को समान होगा, लेकिन जब से मैं संकेत बिंदु स्मृति में कामयाब रहे हैं करने के लिए चीजों के सभी के रूप में जब तक 2006.
// I have 1000000 items, and I want to delete the first 5000
// Copy the pointer array items up the array
CopyMemory(@myList.List[0],
@myList.List[5000],
SizeOf(Pointer) * (myList.Count - 5000));
// Reset the count. Delphi cooperates as long as we're shrinking
myList.Count := myList.Count - 5000;
// You now have tons of unused memory at the end, it's fine
// but if you want to clean house
myList.Capacity := myList.Count;
की जरूरत नहीं है मैं कोड नहीं लिख सकते हैं कहीं और, कोई रिसाव नहीं है।
यहाँ सबूत है:
type
TMyObject = class
index: Integer;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
myList: TList;
i: Integer;
myObject: TMyObject;
begin
// Create a list with 1000000 entries
myList := TList.Create;
for i := 1 to 1000000 do
begin
myObject := TMyObject.Create;
myObject.index := i;
myList.Add(myObject);
end;
// Delete the first 5000
CopyMemory(@myList.List[0],
@myList.List[5000],
SizeOf(Pointer) * (myList.Count - 5000));
myList.Count := myList.Count - 5000;
myList.Capacity := myList.Count;
// Show the new count
ShowMessage(IntToStr(myList.Count));
// Shows that my array now has objects 5001 and up
for i := 0 to 5 do
begin
myObject := TMyObject(myList.Items[i]);
ShowMessage(IntToStr(myObject.index));
end;
end;
सबूत प्रमुख मेमोरी लीक है, लेकिन हम अभी मान दिखाने के लिए ऑब्जेक्ट का निर्माण होगा।
मुझे लगता है कि उपरोक्त को अपनी कक्षा के तरीके के रूप में लागू करने वाली अपनी टीएलआईस्ट कक्षा बहुत अच्छी होगी। –
यहां एक विचार है: यदि आपको पता है कि आपकी सूची में सभी आइटम असाइन किए गए हैं, तो आप उन लोगों को निपटा सकते हैं जिन्हें आप निकालना चाहते हैं और बस TList.Pack() को कॉल करें, जो आंकड़े बताते हैं कि रिक्त स्थान कहां हैं और बाकी सब कुछ एक तरफ ले जाते हैं यथासंभव कुशलतापूर्वक। इसके लिए सभी वस्तुओं के माध्यम से स्कैन की आवश्यकता होती है, इसलिए हो सकता है कि आप जो भी चाहते हों, हो लेकिन यह हटाएं (और इस प्रकार नाइटोफी कॉल को रोकता है) का उपयोग नहीं करता है। पैक का कार्यान्वयन डी 2006 और एक्सई 2 के बीच थोड़ा सा नहीं बदला है, इसलिए आप इसकी दक्षता पर निर्भर कर सकते हैं।
नोट, कि जिन वस्तुओं को आप निकालना चाहते हैं उन्हें शून्य करने के लिए, आप List[aIndex] := nil
का उपयोग कर सकते हैं लेकिन यह अभी भी एक नोटिफ़ाई() कॉल लगाएगा, इसलिए List.List[aIndex] := nil
इसके लिए तेज़ हो सकता है।
क्या आप सुनिश्चित हैं कि बाद के आइटमों को स्थानांतरित करने की आवश्यकता है .. यदि यह एक लिंक्ड सूची के रूप में लागू किया गया है तो यह काफी चीप है। यह नहीं कि यह टिप्पणी प्रश्न के लिए वैध उत्तर प्राप्त करने की आवश्यकता को हटा देती है .. – baash05
क्या हटाने के बाद वस्तुओं का क्रम क्या है? –
@ baash05: मेरा मानना है कि टीएलिस्ट को एक सरणी के रूप में लागू किया गया है। –